home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / pc / files / dsp / 56000tar.z / 56000tar / 56000 / speech / adpcm.asm next >
Assembly Source File  |  1991-11-26  |  121KB  |  3,107 lines

  1. ;
  2. ; This program originally available on the Motorola DSP bulletin board.
  3. ; It is provided under a DISCLAMER OF WARRANTY available from
  4. ; Motorola DSP Operation, 6501 Wm. Cannon Drive W., Austin, Tx., 78735.
  5. ;**************************************************************************
  6. ;
  7. ;   ADPCM.ASM       Full-Duplex 32-kbit/s CCITT ADPCM Algorithm
  8. ;
  9. ; Version 1.0 - 1/27/89
  10. ;
  11. ; This program implements the algorithm defined in CCITT Recommendation
  12. ; G.721: "32 kbit/s Adaptive Differential Pulse Code Modulation" dated
  13. ; August 1986. This version passes all of the mu-law and A-law test
  14. ; sequences as defined in Appendix II of Recommendation G.721.
  15. ;
  16. ; Please refer to the file ADPCM.HLP for further information about
  17. ; this program.
  18. ;
  19. ;**************************************************************************
  20.  
  21.             OPT     CC,CEX                                                                         
  22.  
  23. START       EQU     $0040
  24.  
  25.             ORG     X:$0000
  26.  
  27. ;******************** Encoder variables ***********************************
  28. ;   I = siii 0000 | 0000 0000 | 0000 0000 (ADPCM format)
  29. I_T         DS      1               ;ADPCM codeword
  30. ;   DQ = siii iiii | iiii iii.0 | 0000 0000  (15SM)
  31. DQ_T        DS      1               ;Quantized difference signal
  32. ;   Y = 0iii i.fff | ffff ff00 | 0000 0000  (13SM)
  33. Y_T         DS      1               ;Quantizer scale factor
  34. ;   AP = 0ii.f ffff | fff0 0000 | 0000 0000  (10SM)
  35. AP_T        DS      1               ;Unlimited speed control parameter
  36. ;   AL = 0i.ff ffff | 0000 0000 | 0000 0000  (7SM)
  37. AL_T        DS      1               ;Limited speed control parameter
  38.  
  39. ;******************** Decoder variables ***********************************
  40. I_R         DS      1               ;ADPCM codeword
  41. DQ_R        DS      1               ;Quantized difference signal
  42. Y_R         DS      1               ;Quantizer scale factor
  43. AP_R        DS      1               ;Unlimited speed control parameter
  44. AL_R        DS      1               ;Limited speed control parameter
  45. ;   SP = psss qqqq | 0000 0000 | 0000 0000 (PCM log format)
  46. SP_R        DS      1               ;PCM reconstructed signal
  47.  
  48. ;******************** Temporary variables *********************************
  49. ;   IMAG = 0iii. 0000 | 0000 0000 | 0000 0000
  50. IMAG        DS      1               ;|I|
  51. ;   PKS1 = sXXX XXXX | XXXX XXXX | 0000 0000  (1TC)
  52. PKS1        DS      1               ;XOR of  PK0 & PK1
  53. ;   PKS2 = sXXX XXXX | XXXX XXXX | 0000 0000  (1TC)
  54. PKS2        DS      1               ;XOR of  PK0 & PK2
  55. DATAPTR_T   DS      1               ;Transmit data buffer pointer
  56. DATAPTR_R   DS      1               ;Receive data buffer pointer
  57.  
  58.  
  59. ;******************** Table for quantizing DLN ****************************
  60. ; Used in QUAN routine
  61.  
  62. QUANTAB     DS      8
  63.  
  64. ;******************** Table for unquantizing I ****************************
  65. ; Used in RECONST
  66.  
  67. IQUANTAB    DS      8
  68.  
  69. ;******************** W(I) lookup table ***********************************
  70. ; Used in FUNCTW routine
  71.  
  72. WIBASE      DS      8
  73.  
  74. ;******************** Table used in COMPRESS ******************************
  75.  
  76. TAB         DS      8
  77.  
  78. ;******************** Constants used by FMULT *****************************
  79.  
  80. CONST       DS      6
  81.  
  82. ;******************** Encoder data buffer *********************************
  83. ; DQn (11FL) stored separately as exponent, mantissa, and sign
  84. ;    DQnEXP = 0000 0000 | 0000 0000 | 0000 eeee
  85. ;    DQnMANT = 01mm mmm0 | 0000 0000 | 0000 0000
  86. ;    DQnS = sXXX XXXX | XXXX XXXX | 0000 0000
  87. ; SRn in same format
  88. DATA_T      DSM     24              ;24 word modulo buffer for data,
  89.                                     ; R2 is used as pointer, DATAPTR_T
  90.                                     ; points to start of buffer (DQ1EXP)
  91.                                     ; at beginning of cycle
  92.                                     ;DQ1EXP,DQ1MANT,DQ1S
  93.                                     ;DQ2EXP,DQ2MANT,DQ2S
  94.                                     ;DQ3EXP,DQ3MANT,DQ3S
  95.                                     ;DQ4EXP,DQ4MANT,DQ4S
  96.                                     ;DQ5EXP,DQ5MANT,DQ5S
  97.                                     ;DQ6EXP,DQ6MANT,DQ6S
  98.                                     ;SR1EXP,SR1MANT,SR1S
  99.                                     ;SR2EXP,SR2MANT,SR2S
  100.  
  101. ;******************** Encoder partial product buffer **********************
  102. ;   WBn = siii iiii | iiii iii.f | 0000 0000  (16TC)
  103. ;   WAn in same format
  104. PP_T        DSM     8               ;8 word modulo buffer for partial
  105.                                     ; products, R1 is used as pointer
  106.                                     ;WB1
  107.                                     ;WB2
  108.                                     ;WB3
  109.                                     ;WB4
  110.                                     ;WB5
  111.                                     ;WB6
  112.                                     ;WA1
  113.                                     ;WA2
  114.  
  115. ;******************** Decoder data buffer *********************************
  116. DATA_R      DSM     24              ;24 word modulo buffer for data
  117.                                     ; (same format as DATA_T)
  118.  
  119. ;******************** Decoder partial product buffer **********************
  120. PP_R        DSM     8               ;8 word modulo buffer for partial products
  121.                                     ; (same format as PP_T)
  122.     
  123.  
  124.             ORG     Y:$0000
  125. ;******************** Encoder variables ***********************************
  126. ;   SE = siii iiii | iiii iii.0 | 0000 0000  (15TC)
  127. SE_T        DS      1               ;Signal estimate
  128. ;   SEZ = siii iiii | iiii iii.0 | 0000 0000 (15TC)
  129. SEZ_T       DS      1               ;Partial signal estimate
  130. ;   SR = siii iiii | iiii iiii. | 0000 0000  (16TC)
  131. SR_T        DS      1               ;Reconstructed signal
  132. ;   PK0 = sXXX XXXX | XXXX XXXX | 0000 0000  (1TC)
  133. PK0_T       DS      1               ;Sign of DQ + SEZ
  134. ;   PK1 = sXXX XXXX | XXXX XXXX | 0000 0000  (1TC)
  135. PK1_T       DS      1               ;Delayed sign of DQ + SEZ
  136. ;   PK2 = sXXX XXXX | XXXX XXXX | 0000 0000  (1TC)
  137. PK2_T       DS      1               ;Delayed sign of DQ + SEZ
  138. ;   DMS = 0iii. ffff | ffff f000 | 0000 0000  (12SM)
  139. DMS_T       DS      1               ;Short term average of F(I)
  140. ;   DML = 0iii. ffff | ffff fff0 | 0000 0000  (14SM)
  141. DML_T       DS      1               ;Long term average of F(I)
  142. ;   TDP = i000 0000 | 0000 0000 | 0000 0000  (1TC)
  143. TDP_T       DS      1               ;Tone detect
  144. ;   TD = i000 0000 | 0000 0000 | 0000 0000  (1TC)
  145. TD_T        DS      1               ;Delayed tone detect
  146. ;   YU =  0iii i.fff | ffff ff00 | 0000 0000  (13SM)
  147. YU_T        DS      1               ;Fast quantizer scale factor
  148. ;   YL =  0iii i.fff | ffff ffff | ffff 0000  (19SM)
  149. YL_T        DS      1               ;Slow quantizer scale factor
  150. ;   SIGPK = i000 0000 | 0000 0000 | 0000 0000  (1TC)
  151. SIGPK_T     DS      1               ;Sgn[p(k)] flag
  152. ;   A2P = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  153. A2P_T       DS      1               ;Second order predictor coef
  154. ;   TR = i000 0000 | 0000 0000 | 0000 0000  (1TC)
  155. TR_T        DS      1               ;Transition detect
  156.  
  157. ;******************** Decoder variables ***********************************
  158. SE_R        DS      1               ;Signal estimate
  159. SEZ_R       DS      1               ;Partial signal estimate
  160. SR_R        DS      1               ;Reconstructed signal
  161. PK0_R       DS      1               ;Sign of DQ + SEZ
  162. PK1_R       DS      1               ;Delayed sign of DQ + SEZ
  163. PK2_R       DS      1               ;Delayed sign of DQ + SEZ
  164. DMS_R       DS      1               ;Short term average of F(I)
  165. DML_R       DS      1               ;Long term average of F(I)
  166. TDP_R       DS      1               ;Tone detect
  167. TD_R        DS      1               ;Delayed tone detect
  168. YU_R        DS      1               ;Fast quantizer scale factor
  169. YL_R        DS      1               ;Slow quantizer scale factor
  170. SIGPK_R     DS      1               ;Sgn[p(k)] flag
  171. A2P_R       DS      1               ;Second order predictor coef
  172. TR_R        DS      1               ;Transition detect
  173.  
  174. ;******************** Temporary variables *********************************
  175. LAW         DS      1               ;Select A-law or mu-law
  176. DQMAG       DS      1               ;|DQ|
  177.  
  178. ;******************** Shift constant lookup table *************************
  179. ; Shift constants used for doing left or right shifts by multiplying by a
  180. ; power of 2.  For right shift, some routines use R5 as a base and N5 as
  181. ; and offset for lookup of shift constant.
  182. RSHFT       DS      24
  183. LSHFT
  184.  
  185. ;******************** Misc. constants *************************************
  186. CONST1      DS      3
  187. CONST4      DS      4
  188. CONST8      DS      9
  189. CONST17     DS      16
  190.  
  191. ;******************** Encoder coef. buffer ********************************
  192. ;   Bn = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  193. ;   An in same format
  194. COEF_T      DSM     8               ;8 word modulo buffer for coefs.,
  195.                                     ; R6 is used as pointer
  196.                                     ;B1
  197.                                     ;B2
  198.                                     ;B3
  199.                                     ;B4
  200.                                     ;B5
  201.                                     ;B6
  202.                                     ;A1
  203.                                     ;A2
  204.  
  205. ;******************** Decoder coef. buffer ********************************
  206. COEF_R      DSM     8               ;8 locations for coef. queue
  207.                                     ; (same format as COEF_T)
  208.  
  209.             PAGE
  210.  
  211.             ORG     P:$0000
  212.             JMP     START
  213.  
  214.             ORG     P:START
  215.  
  216.         CLR     A
  217.         MOVEC   #$06,OMR            ;Enable internal ROM tables
  218.         MOVEP   A,X:$FFFE           ;Set BCR for 0 wait states
  219.         JSR     INIT
  220.  
  221. ;**************************************************************************
  222. ;
  223. ;   Encoder
  224. ;
  225. ;**************************************************************************
  226.  
  227. ENCODE  MOVE    #PP_T,R1            ;Set partial product ptr to WB1
  228.         MOVE    X:DATAPTR_T,R2      ;Set data pointer to DQ1EXP
  229.         MOVE    #COEF_T,R6          ;Set coef pointer to B1
  230.         MOVE    #CONST1,R7          ;Set pointer to misc constants
  231.  
  232. ;**************************************************************************
  233. ;       FMULT
  234. ;
  235. ; Multiply predictor coefficients with corresponding
  236. ;   quantized difference signal or reconstructed signal
  237. ;
  238. ;   Data (DQn or SRn) is stored in 11FL format (separate),
  239. ;   & coefficient (Bn or An) is stored in 16TC format.
  240. ;
  241. ; Computes  [An(k-1) * SR(k-n)] or [Bn(k-1) * DQ(k-n)]
  242. ;
  243. ; Flow Description:
  244. ;   1. Convert 16TC An to 13SM AnMAG
  245. ;   2. Convert 13SM AnMAG to 10FL (AnEXP and AnMANT)
  246. ;   3. Add SRnEXP to AnEXP to get WAnEXP (5-bits)
  247. ;   4. Multiply SRnMANT with AnMANT, add '48', and truncate
  248. ;       to 8-bits to get WAnMANT
  249. ;   5. Convert 13FL (WAnEXP & WAnMANT) to 15SM WAnMAG
  250. ;   6. XOR AnS with SRnS to find WAnS
  251. ;   7. Convert 16SM (WAnMAG & WAnS) to 16TC WAn
  252. ;
  253. ; Input:
  254. ;   SRn = (11FL)
  255. ;    SRnEXP = X:(R2) = 0000 0000 | 0000 0000 | 0000 eeee
  256. ;    SRnMANT = X:(R2+1) = 01mm mmm0 | 0000 0000 | 0000 0000
  257. ;    SRnS = X:(R2+2) = sXXX XXXX | XXXX XXXX | 0000 0000
  258. ;       (DQ in same format as SR)
  259. ;
  260. ;   An = Y:(R6) = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  261. ;       (Bn in same format as An)
  262. ;
  263. ; Output:
  264. ;   WAn = X:(R1) = siii iiii | iiii iii.f | 0000 0000  (16TC)
  265. ;       (WBn in same format as WAn)
  266. ;
  267. ;**************************************************************************
  268.  
  269.         MOVE    #CONST,R0           ;Set pointer to FMULT constants
  270.         MOVE    #0,Y1
  271.         DO      #8,ACCUM_T          ;Execute mult 8 times
  272.  
  273. ; 1. Convert 16TC An to 13SM AnMAG
  274.         MOVE    X:(R0)+,X1  Y:(R6),A    ;Get An and mask KF1
  275.         AND     X1,A    X:(R0)+,X1  ;Truncate An to 13 bits (An>>2),
  276.                                     ; get mask KF2
  277.         ABS     A       #$000D,R4   ;Find AnMAG, load
  278.                                     ; exponent bias (13) into R4
  279.         AND     X1,A    #<$7E,X1    ;Truncate any ovrflw, get mask
  280. ;   A1 = 0i.ff ffff | ffff ff00 | 0000 0000 (A2=A0=0)
  281.  
  282. ; 2. Convert 13SM AnMAG to 10FL (AnEXP and AnMANT)
  283.         JNE     <NORMAN_T           ;Test AnMAG
  284.         MOVE    #<$40,A             ;If AnMAG=0, set AnMANT=1<<5,
  285.         MOVE    #0,R4               ; and AnEXP=0
  286.         JMP     <CONTIN_T
  287. NORMAN_T    NORM    R4,A            ;If AnMAG!=0 do NORM iteration
  288.         NORM    R4,A                ; 12 times to find MSB
  289.         NORM    R4,A
  290.         NORM    R4,A
  291.         NORM    R4,A
  292.         NORM    R4,A
  293.         NORM    R4,A
  294.         NORM    R4,A
  295.         NORM    R4,A
  296.         NORM    R4,A
  297.         NORM    R4,A
  298.         NORM    R4,A
  299. ;   A1 = 01?? ???? | ???? ??00 | 0000 0000 = AnMANT
  300. ;   R4 = 0000 0000 | 0000 eeee = AnEXP
  301. CONTIN_T    AND     X1,A    R4,B    ;Truncate AnMANT to 6 bits,
  302.                                     ; move AnEXP to B
  303. ;   A1 = 01mm mmm0 | 0000 0000 | 0000 0000 (A2=A0=0)
  304. ;   B1 = 0000 0000 | 0000 0000 | 0000 eeee (B2=B0=0)
  305.  
  306. ; 3. Add SRnEXP to AnEXP to get WAnEXP (5-bits)
  307.         MOVE    X:(R2)+,X1  A,Y0    ;Get SRnEXP
  308.         ADD     X1,B    X:(R2)+,X1  ;Find WAnEXP=SRnEXP+AnEXP,
  309.                                     ; get SRnMANT 
  310. ;   B1 = 0000 0000 | 0000 0000 | 000e eeee (B2=B0=0)
  311.  
  312. ; 4. Multiply SRnMANT with AnMANT, add '48', and truncate
  313. ;       to 8-bits to get WAnMANT
  314. ;   Y0 = 01mm mmm0 | 0000 0000 | 0000 0000
  315. ;   X1 = 01mm mmm0 | 0000 0000 | 0000 0000
  316.         MPY     Y0,X1,A     X:(R0)+,X0  ;Find WAnMANT, get '48' (KF3)
  317. ;   A1 = 0mmm mmmm | mmmm m000 | 0000 0000 (A2=A0=0)
  318. ;   X0 = 0000 0001 | 1000 0000 | 0000 0000 = '48'
  319.         ADD     X0,A        X:(R0)+,X0  ;Add '48' to WAnMANT, get mask KF4
  320.         AND     X0,A        X:(R0)+,X0  ;Truncate WAnMANT to 8 bits,
  321.                                         ; get '26' (KF5)
  322. ;   A1 = 0mmm mmmm | m000 0000 | 0000 0000 (A2=A0=0)
  323.  
  324. ; 5. Convert 13FL (WAnEXP & WAnMANT) to 15SM WAnMAG
  325. ;   X0 = 0000 0000 | 0000 0000 | 0001 1010 = '26'
  326. ;   B1 = 0000 0000 | 0000 0000 | 000e eeee (B2=B0=0) 
  327.         SUB     X0,B    X:(R0)+,X0  ;Find shift offset (WAnEXP-26),
  328.                                     ; get mask KF6
  329.         JEQ     <TRUNC_T            ;If offset=26 no shift
  330.         JMI     <RIGHT_T            ;If offset<26 do right shift
  331.                                     ;Else offset>26, do left shift
  332.         REP     B1                  ;Offset>26, shift WAnMANT
  333.         LSL     A                   ; left up to 4 times
  334.         JMP     <TRUNC_T
  335. RIGHT_T ABS     B       #>$0F,Y0    ;Find |offset|, get '15'
  336.         CMP     Y0,B    B1,N5       ;Compare |offset| to '15',
  337.                                     ; load offset for shift
  338.         TGE     Y1,A                ;If |offset|>=15 WAnMAG=0
  339.         MOVE    A1,X1               ;Move WAnMANT for shift
  340.         MOVE    Y:(R5+N5),Y0        ;Lookup shift constant
  341.         MPY     Y0,X1,A             ;Shift WAnMANT right up to 14 times
  342. ;   A1 = ?mmm mmmm | mmmm mmmm | ???? ???? (A2=A0=0)
  343. TRUNC_T AND     X0,A    X:(R2)+,X1  Y:(R6)+,B   ;Truncate WAnMAG to 15 bits,
  344.                                     ; get SRnS & AnS
  345. ;   A1 = 0iii iiii | iiii iii.f | 0000 0000 (A2=A0=0)
  346.         NEG     A   A1,X0           ;Find -WAnMAG, save WAnMAG
  347.  
  348. ; 6. XOR AnS with SRnS to find WAnS
  349. ;   B1 = sXXX XXXX | XXXX XXXX | 0000 0000 (B2=sign ext, B0=0)
  350. ;   X1 = sXXX XXXX | XXXX XXXX | 0000 0000
  351.         EOR     X1,B    #CONST,R0   ;Find WAnS (in MSB of B),
  352.                                     ; update pointer to constants
  353.  
  354. ; 7. Convert 16SM (WAnMAG & WAnS) to 16TC WAn
  355.         TPL     X0,A                ;If WAnS=0 use WAnMAG, else use -WAnMAG
  356. ;   A1 = siii iiii | iiii iii.f | 0000 0000  (A2=sign ext, A0=0)
  357.         MOVE    A1,X:(R1)+          ;Save WAn
  358.  
  359. ;**************************************************************************
  360. ;       ACCUM
  361. ;
  362. ; Add predictor outputs to form the partial signal estimate
  363. ;   and the signal estimate
  364. ;
  365. ; SEZ(k) = [B1(k-1) * DQ(k-1)] + ... + [B6(k-1) * DQ(k-6)]
  366. ;        = WB1 + WB2 + ... + WB6
  367. ;
  368. ; SE(k) = SEZ(k) + [A1(k-1) * SR(k-1)] + [A2(k-1) * SR(k-2)]
  369. ;       = SEZ + WA1 + WA2
  370. ;
  371. ; Inputs:
  372. ;   WBn & WAn = X:(R1) = siii iiii | iiii iii.f | 0000 0000  (16TC)
  373. ;
  374. ; Outputs:
  375. ;   SEZ = siii iiii | iiii iii.0 | 0000 0000  (15TC)
  376. ;   SE = siii iiii | iiii iii.0 | 0000 0000  (15TC)
  377. ;
  378. ;**************************************************************************
  379.  
  380. ACCUM_T MOVE    X:(R1)+,A           ;Get WB1
  381.         MOVE    X:(R1)+,X0          ;Get WB2
  382.         ADD     X0,A    X:(R1)+,X0  ;Accumulate WB1&WB2, get WB3
  383.         ADD     X0,A    X:(R1)+,X0  ;Accumulate WB3, get WB4
  384.         ADD     X0,A    X:(R1)+,X0  ;Accumulate WB4, get WB5
  385.         ADD     X0,A    X:(R1)+,X0  ;Accumulate WB5, get WB6
  386.         ADD     X0,A    X:(R1)+,X0  ;Accumulate WB6 to get SEZI, get WA1
  387.         TFR     A,B     Y:(R7)+,X1  ;Copy SEZI, get mask K1
  388.         AND     X1,B    X:AP_T,Y0   ;Truncate SEZI, get AP
  389.         ADD     X0,A    X:(R1)+,X0  ;Accumulate WA1, get WA2
  390.         ADD     X0,A    B1,Y:SEZ_T  ;Accumulate WA2 to get SEI, save SEZ
  391.         AND     X1,A    #<$20,X0    ;Truncate SEI, get '1'
  392.         TFR     Y0,A    A1,Y:SE_T   ;Move AP, save SE
  393.  
  394. ;**************************************************************************
  395. ;       LIMA
  396. ;
  397. ; Limit speed control parameter
  398. ;
  399. ; AL(k) = 1        if AP(k-1) > 1
  400. ;       = AP(k-1)  if AP(k-1) <= 1
  401. ;
  402. ; Inputs:
  403. ;   AP = 0ii.f ffff | fff0 0000 | 0000 0000  (10SM)
  404. ;
  405. ; Outputs:
  406. ;   AL = 0i.ff ffff | 0000 0000 | 0000 0000  (7SM)
  407. ;
  408. ;**************************************************************************
  409.  
  410.         CMP     X0,A    Y:YL_T,B    ;Test AP, get YL
  411.         TGT     X0,A                ;If AP>'1' set AL='1'
  412.         LSL     A       #<$7F,X0    ;Shift to align radix pt., get mask
  413.         AND     X0,A    Y:(R7)+,X0  ;Truncate AL (AP>>2), get mask K2
  414.  
  415. ;**************************************************************************
  416. ;       MIX
  417. ;
  418. ; Form linear combination of fast and slow quantizer
  419. ;   scale factors
  420. ;
  421. ; Y(k) = AL(k) * YU(k-1) + [1 - AL(k)] * YL(k-1)
  422. ;
  423. ; Inputs:
  424. ;   YL = 0iii i.fff | ffff ffff | ffff 0000  (19SM)
  425. ;   AL = 0i.ff ffff | 0000 0000 | 0000 0000  (7SM)
  426. ;   YU = 0iii i.fff | ffff ff00 | 0000 0000  (13SM)
  427. ;
  428. ; Outputs:
  429. ;   Y = 0iii i.fff | ffff ff00 | 0000 0000  (13SM)
  430. ;
  431. ;**************************************************************************
  432.  
  433.         AND     X0,B    A,X0    Y:YU_T,A    ;Truncate YL (YL>>6), get YU
  434.         SUB     B,A     B,Y1    X0,X:AL_T   ;Find DIF=YU-YL, save YL, get AL
  435.         ABS     A       A,B         ;Find DIFM=|DIF|, save DIFS
  436.         MOVE    A1,Y0
  437.         MPY     X0,Y0,A     Y:(R7)+,X0  ;Find DIFM*AL, get mask K3
  438.         AND     X0,A                ;Truncate to find PRODM=(DIFM*AL)>>6
  439.         NEG     A   A1,X0           ;Find -PRODM, save PRODM
  440.         TST     B                   ;Check DIFS
  441.         TPL     X0,A                ;If DIFS=0 PROD=PRODM,
  442.                                     ; else PROD=-PRODM
  443.         ASL     A   Y1,B            ;Line up radix point
  444.         ADD     Y1,A                ;Find Y=PROD+(YL>>6)
  445.         MOVE    A,X:Y_T             ;Save Y
  446.  
  447. ;**************************************************************************
  448. ;
  449. ; Input PCM data (S) here. For simulation purposes the Input 
  450. ; Word from File subroutine on the 56001 ADS board is used.
  451. ;
  452. ;**************************************************************************
  453.  
  454.         MOVE    #1,X0               ;Input PCM word (S)
  455.         JSR     $E002
  456.  
  457. ;**************************************************************************
  458. ;       EXPAND
  459. ;
  460. ; Convert A-law or mu-law PCM to uniform PCM (according to
  461. ;   Recommendation G.711). For further details see Motorola
  462. ;   application bulletin "Logarithmic/Linear Conversion
  463. ;   Routines for DSP56000/1".
  464. ;
  465. ; Input:
  466. ;   S = psss qqqq | 0000 0000 | 0000 0000 (PCM log format)
  467. ;
  468. ; Output:
  469. ;   SL = siii iiii | iiii ii.00 | 0000 0000  (14TC)
  470. ;
  471. ;**************************************************************************
  472.  
  473.         MOVE    A,X0    Y:(R7)+,Y1  ;Get shift constant K4
  474.         MPY     X0,Y1,A     Y:(R7)+,X1  ;Shift S to 8 lsb's of A1, get K5
  475.         AND     X1,A    Y:SE_T,B    ;Mask off sign of S, get SE
  476.         ASR     B       A1,N3       ;sign extend SE, load |S| as offset
  477.         CMPM    Y1,A                ;Check sign of S
  478.         MOVE    X:(R3+N3),A         ;Lookup |SL| from ROM table
  479.         JGE     <SUBTA_T            ;If S=0, SL=|SL|
  480.         NEG     A                   ;If S=1, SL=-|SL|
  481.  
  482. ;**************************************************************************
  483. ;       SUBTA
  484. ;
  485. ; Compute difference signal by subtracting signal estimate
  486. ;       from input signal
  487. ;
  488. ;   D(k) = SL(k) - SE(k)
  489. ;
  490. ; Inputs:
  491. ;   SL = siii iiii | iiii ii.00 | 0000 0000  (14TC) 
  492. ;   SE = siii iiii | iiii iii.0 | 0000 0000  (15TC)
  493. ;
  494. ; Output:
  495. ;   D = siii iiii | iiii iiii. | 0000 0000  (16TC)
  496. ;**************************************************************************
  497.  
  498. SUBTA_T ASR     A       Y:(R7)+,X1  ;Sign extend SL, get mask K6
  499.         ASR     A       #$000E,R0   ;Sign extend SE again, get exp bias (14)
  500.         SUB     B,A     X:Y_T,B     ;Find D=SL-SE, get Y
  501.  
  502. ;**************************************************************************
  503. ;       LOG
  504. ;
  505. ; Convert difference signal from the linear to the log
  506. ;   domain
  507. ;
  508. ; Input:
  509. ;   D = siii iiii | iiii iiii. | 0000 0000  (16TC)
  510. ;
  511. ; Outputs:
  512. ;   DL = 0iii i.fff | ffff 0000 | 0000 0000  (11SM)
  513. ;   DS = sXXX XXXX | XXXX XXXX | 0000 0000  (1TC)
  514. ;
  515. ;**************************************************************************
  516.  
  517.         ABS     A   A,Y1            ;Find DQM=|D|, save DS to Y1
  518.         JNE     <NORMEXP_T          ;Check for DQM=0
  519.         CLR     A       (R7)+       ;If DQM=0 set DL=0,
  520.         MOVE    Y:(R7),X0           ; get mask K8,
  521.         JMP     <SUBTB_T            ; and continue
  522. NORMEXP_T   NORM    R0,A            ;If DQM!=0, do norm iteration
  523.         NORM    R0,A                ; 14 times to find MSB of DQM
  524.         NORM    R0,A
  525.         NORM    R0,A
  526.         NORM    R0,A
  527.         NORM    R0,A
  528.         NORM    R0,A
  529.         NORM    R0,A
  530.         NORM    R0,A
  531.         NORM    R0,A
  532.         NORM    R0,A
  533.         NORM    R0,A
  534.         NORM    R0,A
  535.         NORM    R0,A
  536. ;   A1 = 01?? ???? | ???? ???? | 0000 0000 = normalized DQM  (A2=A0=0)
  537. ;   R0 = 0000 0000 | 0000 eeee = exponent of normalized DQM
  538.  
  539. ;   Get rid of leading "1" in normalized DQM
  540. ;   Truncate mantissa to 7 bits and combine with exponent
  541.         AND     X1,A    Y:LSHFT-19,X0   ;Truncate MANT, get EXP shift
  542. ;   A1 = 00mm mmmm | m000 0000 | 0000 0000 (A2=A0=0)
  543.         MOVE    R0,X1               ;Move EXP to X1
  544.         MPY     X0,X1,A     A,X1    Y:(R7)+,Y0 ;Shift EXP<<19, save MANT to X1,
  545.                                     ; get mask K7
  546.         MOVE    A0,A                ;Move EXP to A1
  547. ;   A1 = 0eee e000 | 0000 0000 | 0000 0000 (A2=A0=0)
  548.         MAC     Y0,X1,A     Y:(R7),X0   ;Shift MANT>>3 & combine with EXP,
  549.                                         ; get mask K8
  550. ;   A1 = 0eee e.mmm | mmmm 0000 | 0000 0000  (A2=A0=0)
  551. ;      = 0iii i.fff | ffff 0000 | 0000 0000  (A2=A0=0)
  552.  
  553. ;**************************************************************************
  554. ;       SUBTB
  555. ;
  556. ; Scale log version of difference signal by subtracting
  557. ;   scale factor
  558. ;
  559. ; DLN = DL - Y
  560. ;
  561. ; Inputs:
  562. ;   DL = 0iii i.fff | ffff 0000 | 0000 0000  (11SM)
  563. ;   Y = 0iii i.fff | ffff ff00 | 0000 0000  (13SM)
  564. ;
  565. ; Output:
  566. ;   DLN = siii i.fff | ffff 0000 | 0000 0000 (12TC)
  567. ;
  568. ;**************************************************************************
  569.  
  570. SUBTB_T AND     X0,B    #QUANTAB,R0     ;Truncate Y to 11 bits (Y>>2),
  571.                                         ; get quantization table base
  572.         SUB     B,A     #>QUANTAB+2,X1  ;Find DLN=DL-Y,
  573.                                         ; get offset for quan. conversion
  574.  
  575. ;**************************************************************************
  576. ;       QUAN
  577. ;
  578. ; Quantize difference signal in log domain
  579. ;
  580. ;    log2|D(k)| - Y(k) | |I(k)|
  581. ;    ------------------+--------
  582. ;      [3.12, + inf)   |   7
  583. ;      [2.72, 3.12)    |   6
  584. ;      [2.34, 2.72)    |   5
  585. ;      [1.91, 2.34)    |   4
  586. ;      [1.38, 1.91)    |   3
  587. ;      [0.62, 1.38)    |   2
  588. ;      [-0.98, 0.62)   |   1
  589. ;      (- inf, -0.98)  |   0
  590. ;
  591. ; Inputs:
  592. ;   DLN = siii i.fff | ffff 0000 | 0000 0000 (12TC)
  593. ;   DS = sXXX XXXX | XXXX XXXX | 0000 0000  (1TC)
  594. ;
  595. ; Output:
  596. ;   I = siii 0000 | 0000 0000 | 0000 0000 (ADPCM format)
  597. ;
  598. ;**************************************************************************
  599.  
  600.         MOVE    X:(R0)+,X0          ;Get quan table value
  601. TSTDLN_T    CMP     X0,A    X:(R0)+,X0  ;Compare to DLN
  602.         JGE     <TSTDLN_T           ;If value<DLN try next range
  603.         MOVE    R0,A                ;When range found...
  604.                                     ; subtract pointer from
  605.         SUB     X1,A    Y:LSHFT-20,X0   ; base to get IMAG=|I|  
  606. ;   A1 = 0000 0000 | 0000 0000 | 0000 0iii (A2=A0=0)
  607.         MOVE    A1,X1
  608.         MPY     X0,X1,A     Y1,B    ;Shift IMAG <<20, result is
  609.                                     ; in A0, move DS (from LOG) into B
  610.         MOVE    A0,A
  611. ;   A1 = 0iii 0000 | 0000 0000 | 0000 0000 (A2=A0=0)
  612.         MOVE    A1,X:IMAG           ;Save IMAG
  613.         TST     A       #<$F0,X0    ;Check IMAG, get invert mask
  614.         JEQ     <INVERT_T           ;If IMAG=0 invert bits
  615.         TST     B                   ;If IMAG!=0, check DS
  616.         JPL     <IOUT_T             ;If DS=1 don't invert IMAG
  617. INVERT_T    EOR     X0,A            ;If DS=0 or IMAG=0,
  618.                                     ; invert IMAG
  619. IOUT_T  MOVE    A1,A                ;Adjust sign extension
  620.         
  621. ;**************************************************************************
  622. ;
  623. ; Output ADPCM data (I) here. For simulation purposes the Output 
  624. ; Word to File subroutine on the 56001 ADS board is used.
  625. ;
  626. ;**************************************************************************
  627.  
  628.         MOVE    #1,X0               ;Output ADPCM word (I)
  629.         JSR     $E004
  630.  
  631. ;**************************************************************************
  632. ;       RECONST
  633. ;
  634. ; Reconstruct quantized difference signal in the log domain
  635. ;
  636. ;     |I(k)| | log2|DQ(k)| - Y(k)
  637. ;    --------+-------------------
  638. ;       7    |      3.32
  639. ;       6    |      2.91
  640. ;       5    |      2.52
  641. ;       4    |      2.13
  642. ;       3    |      1.66
  643. ;       2    |      1.05
  644. ;       1    |      0.031
  645. ;       0    |      - inf
  646. ;
  647. ; Inputs:
  648. ;   I = iiii 0000 | 0000 0000 | 0000 0000  (ADPCM format)
  649. ;
  650. ; Output:
  651. ;   DQLN = siii i.fff | ffff 0000 | 0000 0000  (12TC)
  652. ;   DQS = sXXX 0000 | 0000 0000 | 0000 0000  (1TC)
  653. ;
  654. ;**************************************************************************
  655.  
  656.         MOVE    A,Y1    A,X:I_T     ;Save DQS (sign of I) to Y1
  657.         MOVE    #IQUANTAB,R4        ;Set lookup table base
  658. ;   X1 = 0000 0000 | 0000 0000 | 0000 0iii = |I| (from QUAN)
  659.         MOVE    X1,N4               ;Load |I| as offset
  660.         MOVE    X:Y_T,B             ; into IQUAN table, get Y
  661.         MOVE    X:(R4+N4),A         ;Lookup DQLN
  662.  
  663. ;**************************************************************************
  664. ;       ADDA
  665. ;
  666. ; Add scale factor to log version of quantized difference
  667. ;   signal
  668. ;
  669. ; DQL = DQLN + Y
  670. ;
  671. ; Inputs:
  672. ;   Y = 0iii i.fff | ffff ff00 | 0000 0000  (13SM)
  673. ;   DQLN = siii i.fff | ffff 0000 | 0000 0000  (12TC)
  674. ;
  675. ; Output:
  676. ;   DQL = siii i.fff | ffff 0000 | 0000 0000  (12TC)
  677. ;
  678. ;**************************************************************************
  679.  
  680.         MOVE    Y:(R7)+,Y0          ;Get mask K8 for ADDA
  681.         AND     Y0,B    Y:(R7)+,X0  ;Truncate Y to 11 bits (Y<<2),
  682.                                     ; get mask K9
  683.         ADD     B,A     #<$08,X1    ;Find DQL=DQLN+(Y<<2), get '1'
  684.    
  685. ;**************************************************************************
  686. ;       ANTILOG
  687. ;
  688. ; Convert quantized difference signal from log to linear
  689. ;   domain
  690. ;
  691. ; Input:
  692. ;   DQL = siii i.fff | ffff 0000 | 0000 0000  (12TC)
  693. ;   DQS = sXXX 0000 | 0000 0000 | 0000 0000  (1TC)
  694. ;
  695. ; Outputs:
  696. ;   DQ = siii iiii | iiii iii.0 | 0000 0000  (15SM)
  697. ;
  698. ;**************************************************************************
  699.  
  700.         JPL     <CONVLOG_T          ;If DQL>=0 (DS=0) convert DQL,
  701.                                     ; else DQL<0 (DS=1), set |DQ|=0
  702.         TFR     Y1,A    #<$80,X0    ;Get DQS (MSB of I), get mask
  703.         AND     X0,A    #0,B        ;Mask off DQS, set |DQ|=0
  704. ;   A1 = s000 0000 | 0000 0000 | 0000 0000  (A2=sign ext, A0=0)
  705.         MOVE    B1,Y:DQMAG          ;Save DQMAG=|DQ|
  706.         MOVE    (R7)+               ;Adjust constant pointer
  707.         MOVE    (R7)+
  708.         JMP     <SAVEDQ_T
  709.  
  710. CONVLOG_T   AND     X0,A    A,B     ;Find fractional part (DMN),
  711.                                     ; save DS
  712. ;   A1 = 0000 0.fff | ffff 0000 | 0000 0000  (A2=A0=0)
  713.         OR      X1,A    #<$78,X0    ;Add implied '1' to DMN to
  714.                                     ; find DQT, get integer mask
  715. ;   A1 = 0000 1.fff | ffff 0000 | 0000 0000  (A2=A0=0)
  716.         AND     X0,B    Y:RSHFT+19,Y0   ;Find integer part (DEX),
  717.                                     ; get shift constant
  718. ;   B1 = 0iii i.000 | 0000 0000 | 0000 0000  (B2=B0=0)
  719.         MOVE    B1,X0
  720.         MPY     X0,Y0,B     Y:(R7)+,X0  ;Shift DEX>>19, get '10' (K10)
  721. ;   A1 = 0000 1.fff | ffff 0000 | 0000 0000  (A2=A0=0)
  722. ;   B1 = 0000 0000 | 0000 0000 | 0000 iiii.  (B2=B0=0)
  723.         SUB     X0,B    Y:(R7)+,X0  ;Find DQT shift=DEX-'10',
  724.                                     ; get mask K11
  725.         JEQ     <TRUNCDQM_T         ;If DEX=10, no shift
  726.         JLT     <SHFRDQ_T           ;If DEX<10, shift right
  727.         REP     B1                  ;Else shift DQT left
  728.         LSL     A                   ; up to 4 times
  729.         JMP     <TRUNCDQM_T
  730.  
  731. SHFRDQ_T    NEG     B               ;Find 10-DEX
  732.         MOVE    B1,N5               ;Use 10-DEX for shift lookup
  733.         MOVE    A1,Y0
  734.         MOVE    Y:(R5+N5),X1        ;Lookup shift constant
  735.         MPY     X1,Y0,A             ;Shift DQT right up to 9 times
  736. TRUNCDQM_T  AND     X0,A    #<$80,B ;Truncate to find DQMAG=|DQ|,
  737.                                     ; get sign mask
  738. ;   A1 = 0iii iiii | iiii iii.0 | 0000 0000  (A2=A0=0)
  739.         AND     Y1,B    A1,Y:DQMAG  ;Mask off DQS, save DQMAG           
  740. ;   B1 = s000 0000 | 0000 0000 | 0000 0000  (B2=?, B0=0)
  741.         MOVE    B1,X0
  742.         OR      X0,A                ;Add DQS to DQMAG to get DQ
  743. ;   A1 = siii iiii | iiii iii.0 | 0000 0000  (A2=?, A0=0)
  744. SAVEDQ_T    MOVE    A1,X:DQ_T       ;Save DQ
  745.  
  746. ;**************************************************************************
  747. ;       TRANS
  748. ;
  749. ; Transition detector
  750. ;
  751. ; TR(k) = 1 if TD(k)=1 and |DQ(k)|> 24 x 2**(YL(k))
  752. ;         0 otherwise
  753. ;
  754. ; Inputs:
  755. ;   TD = i000 0000 | 0000 0000 | 0000 0000  (1TC)
  756. ;   YL = 0iii i.fff | ffff ffff | ffff 0000  (19SM)
  757. ;   DQ = siii iiii | iiii iii.0 | 0000 0000  (15SM)
  758. ;
  759. ; Output:
  760. ;   TR = i000 0000 | 0000 0000 | 0000 0000  (1TC)
  761. ;
  762. ;**************************************************************************
  763.  
  764.         MOVE    Y:TD_T,A            ;Get TD
  765.         TST     A   #0,A            ;Check TD, set TR=0
  766.         JEQ     <SAVETR_T           ;If TD=0 save TR=0
  767.                                     ; else test DQ and YL
  768.         MOVE    Y:YL_T,A            ;Get YL
  769.         TFR     A,B     Y:(R7)+,X0  ;Save YL, get mask K12
  770.         AND     X0,A    #<$08,X0    ;Find YLFRAC (YL>>10), get '1'
  771.         OR      X0,A    B,X1    Y:(R7)+,Y1  ;Add implied '1' to YLFRAC,
  772.                                     ; get mask K13
  773.         MPY     Y1,X1,B     Y:(R7)+,X0  ;Find YLINT=YL>>15, get '8' (K14)
  774.         MOVE    B1,B                ;Adjust sign extension
  775.         CMP     X0,B    Y:(R7)+,X0  ;Compare YLINT to '8', get '5' (K15)
  776.         JGT     <MAXTHR_T           ;If YLINT>8 set maximum THR2
  777.         SUB     X0,B                ;Find YLINT-5
  778.         JEQ     <SETDQTHR_T         ;If YLINT=5 don't shift
  779.         JLT     <RSHFT_T            ;If YLINT<5 shift right
  780.  
  781.         REP     B1                  ;Else shift YLFRAC left
  782.         LSL     A                   ; up to 3 times to get THR1
  783.         JMP     <SETDQTHR_T
  784.  
  785. MAXTHR_T    MOVE    #<$7C,A         ;Set maximum THR2 (31<<9)
  786.         JMP     <SETDQTHR_T
  787.  
  788. RSHFT_T NEG     B                   ;Find 5-YLINT
  789.         MOVE    B1,N5               ;Use 5-YLINT for shift lookup
  790.         MOVE    A1,X0
  791.         MOVE    Y:(R5+N5),X1        ;Lookup shift constant
  792.         MPY     X0,X1,A             ;Shift YLFRAC right up to ? times
  793.                                     ; to get THR1
  794. SETDQTHR_T  TFR     A,B     Y:(R7)+,X0  ;Get mask K16
  795.         LSR     B                   ;Find THR2>>1
  796.         AND     X0,B                ;Truncate THR2>>1
  797.         ADD     B,A     #0,X1       ;Find THR2+(THR2>>1)
  798.         LSR     A                   ;Find (THR2+(THR2>>1)>>1
  799.         AND     X0,A    Y:DQMAG,X0  ;Truncate to find DQTHR, get DQMAG
  800.         CMP     X0,A    #<$80,A     ;Compare DQMAG to DQTHR, set TR=1
  801.         TGT     X1,A                ;If DQMAG>DQTHR leave TR=1,
  802.                                     ; else DQMAG<=DQTHR, set TR=0
  803. SAVETR_T    MOVE    A1,Y:TR_T       ;Save TR
  804.  
  805. ;**************************************************************************
  806. ;       ADDB
  807. ;
  808. ; Add quantized difference signal and signal estimate
  809. ;   to form reconstructed signal
  810. ;
  811. ; SR(k-n) = SE(k-n) + DQ(k-n)
  812. ;
  813. ; Inputs:
  814. ;   DQ = siii iiii | iiii iii.0 | 0000 0000  (15SM)
  815. ;   SE = siii iiii | iiii iii.0 | 0000 0000  (15TC)
  816. ;
  817. ; Output:
  818. ;   SR = siii iiii | iiii iiii. | 0000 0000  (16TC)
  819. ;
  820. ;**************************************************************************
  821.  
  822.         MOVE    Y:SE_T,B            ;Get SE
  823.         ASR     B   X:DQ_T,A        ;Sign extend SE to get SEI, get DQS
  824.         TST     A       Y:DQMAG,A   ;Check DQS, get DQMAG
  825.         JPL     <SHFTDQ_T           ;If DQS=0 continue
  826.         NEG     A                   ;Convert DQ to 2's comp
  827. SHFTDQ_T    ASR     A               ;Sign extend DQ to get DQI
  828.         ADD     A,B     #CONST17,R7 ;Find SR=DQ+SE, update const pointer
  829.  
  830. ;**************************************************************************
  831. ;       ADDC
  832. ;
  833. ; Obtain sign of addition of the quantized difference
  834. ;   signal and the partial signal estimate
  835. ;
  836. ; P(k) = DQ(k) + SEZ(k)
  837. ; PK0 = sign of P(k)
  838. ;
  839. ; Inputs:
  840. ;   DQ = siii iiii | iiii iii.0 | 0000 0000  (15SM)
  841. ;   SEZ = siii iiii | iiii iii.0 | 0000 0000 (15TC)
  842. ;
  843. ; Output:
  844. ;   PK0 = sXXX XXXX | XXXX XXXX | 0000 0000  (1TC)
  845. ;   SIGPK = i000 0000 | 0000 0000 | 0000 0000  (1TC)
  846. ;
  847. ;**************************************************************************
  848.  
  849.         MOVE    B1,Y:SR_T           ;Save SR
  850.         MOVE    Y:SEZ_T,B           ;Get SEZ
  851.         ASR     B                   ;Sign extend SEZ to SEZI
  852.         ADD     B,A     #0,B        ;Find DQSEZ=DQ+SEZ,
  853.                                     ; set SIGPK=0
  854.         TST     A   #<$80,X0        ;Check DQSEZ, get '1'
  855.         TEQ     X0,B                ;If DQSEZ=0, SIGPK=1,
  856.                                     ; else SIGPK=0
  857.  
  858.         MOVE    Y:PK1_T,X0
  859.         MOVE    X0,Y:PK2_T          ;Delay previous PK1
  860.         MOVE    Y:PK0_T,X0
  861.         MOVE    X0,Y:PK1_T          ;Delay previous PK0
  862.         MOVE    A1,Y:PK0_T          ;Save new PK0
  863.         MOVE    B1,Y:SIGPK_T        ;Save SIGPK
  864.         EOR     X0,A    Y:PK2_T,X0  ;Find PKS1=PK0**PK1
  865.                                     ; for UPA1 & UPA2
  866.         MOVE    A1,X:PKS1           ;Save PKS1
  867.         MOVE    Y:PK0_T,A
  868.         EOR     X0,A    #3,N2       ;Find PKS2=PK0**PK2 for UPA2
  869.         MOVE    A1,X:PKS2           ;Save PKS2
  870.         MOVE    (R2)+               ;Adjust data buffer pointer so
  871.         MOVE    (R2)+               ; that R2 points to DQ1S
  872.  
  873. ;**************************************************************************
  874. ;       XOR
  875. ;
  876. ; Find one bit "exclusive or" of the sign of difference
  877. ;   signal and the sign of delayed difference signal.
  878. ;
  879. ; Un = sgn[DQ(k)] XOR sgn[DQ(k-n)]
  880. ;
  881. ; Inputs:
  882. ;   DQ = siii iiii | iiii iii.0 | 0000 0000 (15SM)
  883. ;   DQnS = X:(R2+n) sXXX XXXX | XXXX XXXX | 0000 0000
  884. ;
  885. ; Outputs:
  886. ;   Un = sXXX XXXX | XXXX XXXX | 0000 0000 (1TC)
  887. ;
  888. ;**************************************************************************
  889. ;**************************************************************************
  890. ;       UPB
  891. ;
  892. ; Update the coefficients of the sixth order predictor
  893. ;
  894. ; Bn(k) = [1-(2**-8)] * Bn(k-1)
  895. ;           + (2**-7) * sgn[DQ(k)] * sgn[DQ(k-n)]
  896. ;
  897. ; Inputs:
  898. ;   Bn = Y:(R6+n) = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  899. ;   DQ = siii iiii | iiii iii.0 | 0000 0000 (15SM)
  900. ;   Un = sXXX XXXX | XXXX XXXX | 0000 0000 (1TC)
  901. ;
  902. ; Outputs:
  903. ;   BnP = Y:(R6+n) = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  904. ;
  905. ;**************************************************************************
  906.  
  907.         MOVE    Y:DQMAG,A           ;Get DQMAG
  908.         TST     A   X:DQ_T,Y0       ;Check DQMAG, get DQS
  909.         JNE     <XORUPB_T           ;If DQMAG!=0 use section with XOR,
  910.                                     ; else use section with no XOR
  911.                                     ; (because UGBn=0 if DQMAG=0)
  912.  
  913. ; UPB without XOR
  914.         MOVE    Y:RSHFT+8,X1        ;Get shift constant
  915.         MOVE    (R7)+               ;Adjust constant pointer
  916.         MOVE    (R7)+
  917.         MOVE    Y:(R7)+,X0          ;Get mask K19
  918.         DO      #6,ENDLOOP_T        ;Do UPB for B1-B6
  919.         MOVE    X:(R2)+N2,A     Y:(R6),Y1   ;Get Bn (& DQnS but don't use)
  920.         MPY     X1,Y1,A             ;Find Bn>>8
  921.         AND     X0,A                ;Truncate (Bn>>8)
  922.         NEG     A                   ;Find UBn=ULBn=-(Bn>>8)
  923.         ADD     Y1,A                ;Find BnP=Bn+UBn
  924.         MOVE    A1,Y:(R6)+          ;Store BnP to Bn
  925. ENDLOOP_T   JMP     <UPA2_T
  926.  
  927. ; UPB with XOR
  928. XORUPB_T    MOVE    Y:(R7)+,X0      ;Get +gain (K17)
  929.         DO      #6,UPTR_T           ;Do UPB and XOR for B1-B6
  930.         MOVE    X:(R2)+N2,A     Y:(R6),Y1   ;Get Bn & DQnS
  931.         EOR     Y0,A    Y:(R7)+,X1  ;Find Un=DQS**DQnS (XOR),
  932.                                     ; get -gain (K18)
  933.         TPL     X0,A                ;If Un=0 set UGBn=+gain
  934.         TMI     X1,A                ;If Un=1 set UGBn=-gain
  935.         MOVE    Y:RSHFT+8,X1        ;Get shift constant
  936.         MPY     X1,Y1,B     Y:(R7)-,X1  ;Shift Bn>>8, get mask K19
  937.         AND     X1,B                ;Truncate (Bn>>8)
  938.         NEG     B                   ;Find ULBn=-(Bn>>8)
  939.         ADD     B,A                 ;Find UBn=UGBn+ULBn
  940.         ADD     Y1,A                ;Find BnP=Bn+UBn
  941.         MOVE    A1,Y:(R6)+          ;Store BnP to Bn
  942. UPTR_T  MOVE    (R7)+               ;Adjust constant pointer
  943.         MOVE    (R7)+
  944.  
  945. ;**************************************************************************
  946. ;       UPA2
  947. ;
  948. ; Update the A2 coefficient of the second order predictor.
  949. ;
  950. ; A2(k) = [1-(2**-7)] * A2(k-1)
  951. ;           + (2**-7) * { sgn[P(k)] * sgn[P(k-2)]
  952. ;               - F[A1(k-1)] * sgn[P(k)] * sgn[P(k-1)] }
  953. ;
  954. ; F[A1(k)] = 4 * A1       if |A1|<=(2**-1)
  955. ;          = 2 * sgn(A1)  if |A1|>(2**-1)
  956. ;
  957. ; Inputs:
  958. ;   A1 = Y:(R6) = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  959. ;   A2 = Y:(R6+1) = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  960. ;   SIGPK = i000 0000 | 0000 0000 | 0000 0000  (1TC)
  961. ;   PK0 = sXXX XXXX | XXXX XXXX | 0000 0000  (1TC)
  962. ;   PK1 = sXXX XXXX | XXXX XXXX | 0000 0000  (1TC)
  963. ;   PK2 = sXXX XXXX | XXXX XXXX | 0000 0000  (1TC)
  964. ;     (Note: PKS1 & PKS2 have been previously calculated)
  965. ;
  966. ; Outputs:
  967. ;   A2T = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  968. ;
  969. ;**************************************************************************
  970.  
  971. UPA2_T  MOVE    X:PKS2,A            ;Get PKS2=PK0**PK2
  972.         TST     A   #<$10,Y0        ;Check PKS2, get '+1'
  973.         MOVE    #<$F0,Y1            ;Get '-1'
  974.         TPL     Y0,A                ;If PKS2=0, set UGA2A='+1'
  975.         TMI     Y1,A                ;If PKS2=1, set UGA2A='-1'
  976.         MOVE    A,X1    Y:(R6)+,A   ;Save UGA2A, get A1
  977.         MOVE    Y:(R7)+,Y0          ;Get '+1.99' (K20)
  978.         CMP     Y0,A    Y:(R7)+,Y1  ;Check A1, get '-1.99' (K21)
  979.         TGT     Y0,A                ;If A1>=1/2, set FA1='1.99'
  980.         CMP     Y1,A    X:PKS1,B    ;Check A1 again, get PKS1=PK0**PK1
  981.         TLT     Y1,A                ;If A1<=-1/2, set FA1='-1.99'
  982.         TST     B       #0,X0       ;Check PKS1
  983.         JMI     <FINDSUM_T          ;If PKS1=1, FA=FA1
  984.         NEG     A                   ; else PKS1=0, set FA=-FA1
  985. FINDSUM_T   ADD     X1,A    Y:RSHFT+5,Y1    ;Find UGA2B=UGA2A+FA,
  986.                                     ; get shift constant
  987.         MOVE    A,X1
  988.         MPY     X1,Y1,A     Y:(R7)+,X1  ;Find UGA2B>>7, get mask K22
  989.         AND     X1,A    Y:SIGPK_T,B ;Truncate UGA2, get SIGPK
  990.         TST     B   Y:(R6),Y0       ;Check SIGPK, get A2
  991.         TMI     X0,A                ;If SIGPK=1, set UGA2=0
  992.         MOVE    Y:RSHFT+7,X0        ;Get shift constant
  993.         MPY     Y0,X0,B             ;Find A2>>7
  994.         AND     X1,B                ;Truncate to find A2>>7
  995.         NEG     B       #<$D0,X0    ;Find ULA2=-(A2>>7), get A2LL
  996.         ADD     B,A     #<$30,X1    ;Find UA2=UGA2+ULA2, get A2UL
  997.         ADD     Y0,A    Y:(R7)+,Y1  ;Find A2T=A2+UA2, get -gain (K23)
  998.  
  999. ;**************************************************************************
  1000. ;       LIMC
  1001. ;
  1002. ; Limit the A2 coefficient of the second order predictor.
  1003. ;
  1004. ;   |A2(k)| <= '0.75' 
  1005. ;
  1006. ; Inputs:
  1007. ;   A2T = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  1008. ;
  1009. ; Outputs:
  1010. ;   A2P = Y:(R6) = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  1011. ;
  1012. ;**************************************************************************
  1013.  
  1014.         CMP     X0,A    Y:(R7)+,Y0  ;Check A2P, get +gain (K24)
  1015.         TLT     X0,A                ;If A2P<-0.75, set A2P=-0.75
  1016.         CMP     X1,A    X:PKS1,B    ;Check A2P again, get PKS1=PK0**PK1
  1017.         TGT     X1,A                ;If A2P>0.75, set A2P=0.75
  1018.         MOVE    A,Y:A2P_T           ;Save A2P
  1019.         MOVE    A,Y:(R6)-           ;Save A2P to A2
  1020.  
  1021. ;**************************************************************************
  1022. ;       UPA1
  1023. ;
  1024. ; Update the A1 coefficient of the second order predictor.
  1025. ;
  1026. ; A1(k) = [1-(2**-8)] * A1(k-1)
  1027. ;           + 3 * (2**-8) * sgn[P(k)] * sgn[P(k-1)]
  1028. ;
  1029. ; Inputs:
  1030. ;   A1 = Y:(R6) = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  1031. ;   SIGPK = Y:(R0) = i000 0000 | 0000 0000 | 0000 0000  (1TC)
  1032. ;   PK0 = sXXX XXXX | XXXX XXXX | 0000 0000  (1TC)
  1033. ;   PK1 = sXXX XXXX | XXXX XXXX | 0000 0000  (1TC)
  1034. ;     (Note: PKS1 has been previously calculated)
  1035. ;
  1036. ; Outputs:
  1037. ;   A1T = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  1038. ;
  1039. ;**************************************************************************
  1040.  
  1041.         TST     B       Y:SIGPK_T,B ;Check PKS1, get SIGPK
  1042.         TPL     Y0,A                ;If PKS=0, set UGA1=+gain
  1043.         TMI     Y1,A                ;If PKS=1, set UGA1=-gain
  1044.         TST     B       #0,X0       ;Check SIGPK
  1045.         TMI     X0,A                ;If SIGPK=1, set UGA1=0
  1046.         MOVE    Y:(R6),X1           ;Get A1
  1047.         MOVE    Y:RSHFT+8,Y0        ;Get shift constant
  1048.         MPY     Y0,X1,B     Y:(R7)+,X0  ;Find A1>>8, get mask K25
  1049.         AND     X0,B                ;Truncate (A1>>8)
  1050.         NEG     B                   ;Find ULA1=-(A1>>8)
  1051.         ADD     B,A     #<$3C,B     ;Find UA1=UGA1+ULA1,
  1052.                                     ; get OME='1-(2**-4)'
  1053.         ADD     X1,A    Y:A2P_T,X0  ;Find A1T=A1+UA1, get A2P
  1054.  
  1055. ;**************************************************************************
  1056. ;       LIMD
  1057. ;
  1058. ; Limit the A1 coefficient of the second order predictor.
  1059. ;
  1060. ;   |A1(k)| <= [1-(2**-4)] - A2(k)
  1061. ;
  1062. ; Inputs:
  1063. ;   A1T = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  1064. ;   A2P = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  1065. ;
  1066. ; Outputs:
  1067. ;   A1P = Y:(R6) = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  1068. ;
  1069. ;**************************************************************************
  1070.  
  1071.         SUB     X0,B                ;Find A1UL=OME-A2P
  1072.         CMP     B,A     B,X0        ;Check A1T
  1073.         TGT     X0,A                ;If A1T>A1UL, set A1P=A1UL
  1074.         NEG     B       (R2)+       ;Find A1LL=-A1UL=A2P-OME
  1075.         CMP     B,A     B,X0        ;Check A1T again
  1076.         TLT     X0,A                ;If A1T<A1LL, set A1P=A1LL
  1077.         MOVE    A1,Y:(R6)+          ;Store A1P to A1
  1078.         MOVE    (R6)+               ;Adjust coef pointer
  1079.  
  1080. ;**************************************************************************
  1081. ;       FLOATA
  1082. ;
  1083. ; Converts the quantized difference signal from 15-bit
  1084. ;   signed magnitude to floating pt. format (11FL - sign,
  1085. ;   exp, and mant stored separately)
  1086. ;
  1087. ; Inputs:
  1088. ;   DQ = siii iiii | iiii iii.0 | 0000 0000 (15SM)
  1089. ;
  1090. ; Outputs:
  1091. ;   DQ0 = (11FL)
  1092. ;    DQ0EXP = X:(R2) = 0000 0000 | 0000 0000 | 0000 eeee
  1093. ;    DQ0MANT = X:(R2+1) = 01mm mmm0 | 0000 0000 | 0000 0000
  1094. ;    DQ0S = X:(R2+2) = sXXX XXXX | XXXX XXXX | 0000 0000
  1095. ;
  1096. ;**************************************************************************
  1097.  
  1098.         MOVE    X:DQ_T,Y0           ;Get DQS
  1099.         MOVE    Y:DQMAG,A           ;Get MAG=DQMAG
  1100.         TST     A   #$000E,R0       ;Check MAG, get exponent bias (14)
  1101.         JNE     <NORMDQ_T           ;Test MAG
  1102.         MOVE    #<$40,A             ;If MAG=0 set MANT=100000,
  1103.         MOVE    #0,R0               ; and EXP=0
  1104.         JMP     <TRUNCDQ_T
  1105. NORMDQ_T    NORM    R0,A            ;If MAG!=0 do NORM iteration 13
  1106.         NORM    R0,A                ; times to find MSB of MAG
  1107.         NORM    R0,A
  1108.         NORM    R0,A
  1109.         NORM    R0,A
  1110.         NORM    R0,A
  1111.         NORM    R0,A
  1112.         NORM    R0,A
  1113.         NORM    R0,A
  1114.         NORM    R0,A
  1115.         NORM    R0,A
  1116.         NORM    R0,A
  1117.         NORM    R0,A
  1118. ;   A1 = 01?? ???? | ???? ???0 | 0000 0000 = normalized MAG (A2=A0=0)
  1119. ;   R0 = 0000 0000 | 0000 eeee = exponent of normalized MAG
  1120.  
  1121. TRUNCDQ_T   MOVE    #<$7E,X0        ;Get mask
  1122.         AND     X0,A    R0,X:(R2)+  ;Truncate MANT to 6 bits,
  1123.                                     ; save EXP to DQ1EXP
  1124. ;   A1 = 01mm mmm0 | 0000 0000 | 0000 0000  (A2=A0=0)
  1125.         MOVE    A1,X:(R2)+          ;Save MANT to DQ1MANT
  1126.         MOVE    Y0,X:(R2)+          ;Save DQ to DQ1S
  1127.  
  1128. ;**************************************************************************
  1129. ;       FLOATB
  1130. ;
  1131. ; Converts the reconstructed signal from 16-bit two's 
  1132. ;   complement to floating pt. format (11FL - sign,
  1133. ;   exp, and mant stored separately)
  1134. ;
  1135. ; Inputs:
  1136. ;   SR = siii iiii | iiii iiii. | 0000 0000  (16TC)
  1137. ;
  1138. ; Outputs:
  1139. ;   SR0 = (11FL)
  1140. ;    SR0EXP = X:(R2) = 0000 0000 | 0000 0000 | 0000 eeee
  1141. ;    SR0MANT = X:(R2+1) = 01mm mmm0 | 0000 0000 | 0000 0000
  1142. ;    SR0S = X:(R2+2) = sXXX XXXX | XXXX XXXX | 0000 0000
  1143. ;
  1144. ;**************************************************************************
  1145.  
  1146.         MOVE    #15,N2
  1147.         MOVE    Y:SR_T,B            ;Get SR
  1148.         MOVE    (R2)+N2             ;Adjust data pointer
  1149.         ABS     B       B,Y0        ;Find MAG=|SR|, save SRS
  1150.         TST     B   #$000F,R0       ;Load exponent bias
  1151.         JNE     <NORMSR_T           ;Test MAG
  1152.         MOVE    #<$40,B             ;If MAG=0 set MANT=100000,
  1153.         MOVE    #0,R0               ; and EXP=0
  1154.         JMP     <TRUNCSR_T
  1155. NORMSR_T    NORM    R0,B            ;If MAG!=0 do NORM iteration 14
  1156.         NORM    R0,B                ; times to find MSB of MAG
  1157.         NORM    R0,B
  1158.         NORM    R0,B
  1159.         NORM    R0,B
  1160.         NORM    R0,B
  1161.         NORM    R0,B
  1162.         NORM    R0,B
  1163.         NORM    R0,B
  1164.         NORM    R0,B
  1165.         NORM    R0,B
  1166.         NORM    R0,B
  1167.         NORM    R0,B
  1168.         NORM    R0,B
  1169. ;   A1 = 01?? ???? | ???? ???0 | 0000 0000  (A2=A0=0)
  1170. ;   R0 = 0000 0000 | 0000 eeee = exponent of normalized MAG
  1171.  
  1172. TRUNCSR_T   AND     X0,B    R0,X:(R2)+  ;Truncate MANT to 6 bits,
  1173.                                     ; save EXP to SR1EXP
  1174. ;   A1 = 01mm mmm0 | 0000 0000 | 0000 0000  (A2=A0=0)
  1175.         MOVE    B1,X:(R2)+          ;Save MANT to SR1MANT
  1176.         MOVE    Y0,X:(R2)+          ;Save SR to SR1S
  1177.         MOVE    #3,N2
  1178.         MOVE    Y:A2P_T,B           ;Get A2P
  1179.         MOVE    (R2)+N2             ;Adjust data pointer
  1180.  
  1181. ;**************************************************************************
  1182. ;       TONE
  1183. ;
  1184. ; Partial band signal detection
  1185. ;
  1186. ; TD(k) = 1 if A2(k) < -0.71875
  1187. ;         0 otherwise
  1188. ;
  1189. ; Inputs:
  1190. ;   A2P = si.ff ffff | ffff ffff | 0000 0000  (16TC)
  1191. ;
  1192. ; Output:
  1193. ;   TDP = i000 0000 | 0000 0000 | 0000 0000  (1TC)
  1194. ;
  1195. ;**************************************************************************
  1196.  
  1197.         CLR     A   #<$D2,X0        ;Get '-.71875', set TDP=0
  1198.         CMP     X0,B    #<$80,X1    ;Check A2P, get '1'
  1199.         TLT     X1,A                ;If A2P<-.71875 set TDP=1, else TDP=0
  1200.         MOVE    A1,Y:TDP_T          ;Save TDP
  1201.         MOVE    A1,Y:TD_T           ;Save TDP to TD
  1202.  
  1203. ;**************************************************************************
  1204. ;       TRIGB
  1205. ;
  1206. ; Predictor trigger block
  1207. ;
  1208. ; If TR(k) = 1, An(k)=Bn(k)=TD(k)=0
  1209. ;
  1210. ; Inputs:
  1211. ;   TR = i000 0000 | 0000 0000 | 0000 0000  (1TC)
  1212. ;   BnP = si.ff ffff | ffff ffff | 0000 0000  (16TC)
  1213. ;   AnP = si.ff ffff | ffff ffff | 0000 0000  (16TC)
  1214. ;   TDP = i000 0000 | 0000 0000 | 0000 0000  (1TC)
  1215. ;
  1216. ; Output:
  1217. ;   BnR = si.ff ffff | ffff ffff | 0000 0000  (16TC)
  1218. ;   AnR = si.ff ffff | ffff ffff | 0000 0000  (16TC)
  1219. ;   TDR = i000 0000 | 0000 0000 | 0000 0000  (1TC)
  1220. ;
  1221. ;**************************************************************************
  1222.  
  1223.         MOVE    Y:TR_T,B            ;Get TR
  1224.         TST     B       #0,A        ;Test TR
  1225.         JEQ     <FUNCTF_T           ;If TR=0 continue
  1226.         MOVE    A,Y:TD_T            ;If TR=1, set TDR=0,
  1227.         MOVE    A,Y:(R6)+           ; and B1-B6,A1,A2=0
  1228.         MOVE    A,Y:(R6)+
  1229.         MOVE    A,Y:(R6)+
  1230.         MOVE    A,Y:(R6)+
  1231.         MOVE    A,Y:(R6)+
  1232.         MOVE    A,Y:(R6)+
  1233.         MOVE    A,Y:(R6)+
  1234.         MOVE    A,Y:(R6)+
  1235.  
  1236. ;**************************************************************************
  1237. ;       FUNCTF
  1238. ;
  1239. ; Maps quantizer output I into F(I) function
  1240. ;
  1241. ;  |I(k)|  | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
  1242. ; ---------+---+---+---+---+---+---+---+---+
  1243. ;  F[I(k)] | 7 | 3 | 1 | 1 | 1 | 0 | 0 | 0 |
  1244. ;
  1245. ; Inputs:
  1246. ;   I = siii 0000 | 0000 0000 | 0000 0000
  1247. ;
  1248. ; Output:
  1249. ;   FI = 0iii. 0000 | 0000 0000 | 0000 0000  (3SM)
  1250. ;   IMAG
  1251. ;
  1252. ;**************************************************************************
  1253.  
  1254. FUNCTF_T    MOVE    #<$20,X0
  1255.         MOVE    X:IMAG,A            ;Get |I|
  1256.         CMP     X0,A    #<$50,X0    ;Test for |I|<=2
  1257.         JLE     <RANGE0_T
  1258.         CMP     X0,A    #<$60,X0    ;Test for 3<=|I|<=5
  1259.         JLE     <RANGE1_T
  1260.         CMP     X0,A                ;Test for |I|=6
  1261.         JEQ     <RANGE3_T
  1262.         MOVE    #<$70,A             ;|I|=7, set F[I]=7
  1263.         JMP     <FILTA_T
  1264. RANGE3_T    MOVE    #<$30,A         ;|I|=6, set F[I]=3
  1265.         JMP     <FILTA_T
  1266. RANGE1_T    MOVE    #<$10,A         ;|I|=3,4,or 5, set F[I]=1
  1267.         JMP     <FILTA_T
  1268. RANGE0_T    CLR     A               ;|I|=0,1,or 2, set F[I]=0
  1269.  
  1270. ;**************************************************************************
  1271. ;       FILTA
  1272. ;
  1273. ; Update short term average of F(I)
  1274. ;
  1275. ; DMS(k) = (1 - 2**(-5)) * DMS(k-1) + 2**(-5) * F[I(k)]
  1276. ;
  1277. ; Inputs:
  1278. ;   FI = 0iii. 0000 | 0000 0000 | 0000 0000  (3SM)
  1279. ;   DMS = 0iii. ffff | ffff f000 | 0000 0000  (12SM)
  1280. ;
  1281. ; Output:
  1282. ;   DMSP = 0iii. ffff | ffff f000 | 0000 0000  (12SM)
  1283. ;
  1284. ;**************************************************************************
  1285.  
  1286. FILTA_T MOVE    Y:DMS_T,Y0          ;Get DMS
  1287.         SUB     Y0,A    A,B         ;Find DIF=FI-DMS, save FI
  1288.         MOVE    A,X0    Y:(R7)+,Y1  ;Save DIF, get mask K26
  1289.         MPY     X0,Y1,A Y:(R7)+,X0  ;Find DIFSX=DIF>>5, get mask K27
  1290.         AND     X0,A    Y:DML_T,Y1  ;Truncate DIFSX, get DML
  1291.         ADD     Y0,A    Y:RSHFT+7,X1    ;Find DMSP=DIFSX+DMS
  1292.  
  1293. ;**************************************************************************
  1294. ;       FILTB
  1295. ;
  1296. ; Update long term average of F(I)
  1297. ;
  1298. ; DML(k) = (1 - 2**(-7)) * DML(k-1) + 2**(-7) * F[I(k)]
  1299. ;
  1300. ; Inputs:
  1301. ;   FI = 0iii. 0000 | 0000 0000 | 0000 0000  (3SM)
  1302. ;   DML = 0iii. ffff | ffff fff0 | 0000 0000  (14SM)
  1303. ;
  1304. ; Output:
  1305. ;   DMLP = 0iii. ffff | ffff fff0 | 0000 0000  (14SM)
  1306. ;
  1307. ;**************************************************************************
  1308.  
  1309.         SUB     Y1,B    A1,Y:DMS_T  ;Find DIF=FI-DML
  1310.         MOVE    B1,X0
  1311.         MPY     X0,X1,B Y:(R7)+,X0  ;Find DFISX=DIF>>7, get mask K28
  1312.         AND     X0,B                ;Truncate DIFSX
  1313.         ADD     Y1,B    Y:RSHFT+3,X1    ;Find DMLP=DIFSX+DML
  1314.  
  1315. ;**************************************************************************
  1316. ;       SUBTC
  1317. ;
  1318. ; Compute magnitude of the difference of short and long
  1319. ;  term functions of quantizer output sequence and then
  1320. ;  perform threshold comparison for quantizing speed control
  1321. ;  parameter.
  1322. ;
  1323. ; AX = 1  if Y(k)>=3, TD(k)=1, & |DMS(k)-DML(k)|>(2**-3)*DML(k)
  1324. ;    = 0  otherwise
  1325. ;
  1326. ; Input:
  1327. ;   Y = 0iii i.fff | ffff ff00 | 0000 0000  (13SM)
  1328. ;   DMSP = 0iii. ffff | ffff f000 | 0000 0000  (12SM)
  1329. ;   DMLP = 0iii. ffff | ffff fff0 | 0000 0000  (14SM)
  1330. ;   TDP = i000 0000 | 0000 0000 | 0000 0000  (1TC)
  1331. ;
  1332. ; Output:
  1333. ;   AX = 0i0.0 0000 | 0000 0000 | 0000 0000  (1SM)
  1334. ;
  1335. ;**************************************************************************
  1336.  
  1337.         SUB     B,A     B1,Y:DML_T  ;Find DIF=DMSP-DMLP, save DML
  1338.         ABS     A       B1,Y0       ;Find DIFM=|DIF|
  1339.         MPY     X1,Y0,B     #<$18,Y0    ;Find DTHR=DMLP>>3, get '3'
  1340.         AND     X0,B    #<$40,X0    ;Truncate DTHR, get '1'
  1341.         CMP     B,A     #0,B        ;Compare DIFM & DTHR, set AX=0
  1342.         TGE     X0,B                ;If DIFM>=DTHR set AX=1
  1343.         MOVE    Y:TDP_T,A           ;Get TDP
  1344.         TST     A       X:Y_T,A     ;Check TDP, get Y
  1345.         TNE     X0,B                ;If TDP!=0 set AX=1
  1346.         CMP     Y0,A    X:AP_T,X1   ;Check for Y<"3", get AP
  1347.         TLT     X0,B                ;If Y<"3" set AX=1
  1348.  
  1349. ;**************************************************************************
  1350. ;       FILTC
  1351. ;
  1352. ; Low pass filter of speed control parameter
  1353. ;
  1354. ; AP(k) = (1-2**(-4)) * AP(k-1) + AX
  1355. ;
  1356. ; Inputs:
  1357. ;   AX = 0i0.0 0000 | 0000 0000 | 0000 0000  (1SM)
  1358. ;   AP = 0ii.f ffff | fff0 0000 | 0000 0000  (10SM)
  1359. ;
  1360. ; Outputs:
  1361. ;   APP = 0ii.f ffff | fff0 0000 | 0000 0000  (10SM)
  1362. ;
  1363. ;**************************************************************************
  1364.  
  1365.         SUB     X1,B    Y:RSHFT+4,Y0    ;Find DIF=AX-AP
  1366.         MOVE    B1,X0
  1367.         MPY     X0,Y0,A     Y:(R7)+,X0  ;Find DIFSX=DIF>>4, get K29
  1368.         AND     X0,A    Y:TR_T,B    ;Truncate DIFSX, get TR
  1369.         ADD     X1,A    #<$20,X0    ;Find APP=DIFSX+AP, get '1'
  1370.  
  1371. ;**************************************************************************
  1372. ;       TRIGA
  1373. ;
  1374. ; Speed control trigger block
  1375. ;
  1376. ; AP(k) = AP(k) if TR(k)=0
  1377. ;       =  1    if TR(k)=1
  1378. ;
  1379. ; Inputs:
  1380. ;   TR = i000 0000 | 0000 0000 | 0000 0000  (1TC)
  1381. ;   APP = 0ii.f ffff | fff0 0000 | 0000 0000  (10SM)
  1382. ;
  1383. ; Outputs:
  1384. ;   APR = 0ii.f ffff | fff0 0000 | 0000 0000  (10SM)
  1385. ;
  1386. ;**************************************************************************
  1387.  
  1388.         TST     B   X:IMAG,X1       ;Check TR, get IMAG
  1389.         TMI     X0,A                ;If TR=1 set APR=1, else APR=APP
  1390.         MOVE    A1,X:AP_T           ;Save APR to AP
  1391.  
  1392. ;**************************************************************************
  1393. ;       FUNCTW
  1394. ;
  1395. ; Map quantizer output into logarithmic version of scale
  1396. ;  factor multiplier
  1397. ;
  1398. ;  |I(k)|  |  7  |  6  |  5  |  4  |  3  |  2  |  1  |  0  |
  1399. ; ---------+-----+-----+-----+-----+-----+-----+-----+-----+
  1400. ;   W(I)   |70.13|22.19|12.38| 7.00| 4.00| 2.56| 1.13|-0.75|
  1401. ;
  1402. ; Inputs:
  1403. ;   I = siii. 0000 | 0000 0000 | 0000 0000  (ADPCM format)
  1404. ;
  1405. ; Outputs:
  1406. ;   WI = siii iiii. | ffff 0000 | 0000 0000  (12TC)
  1407. ;
  1408. ;**************************************************************************
  1409.  
  1410.         MOVE    Y:RSHFT+20,X0       ;Get shift constant
  1411.         MPY     X0,X1,A     #WIBASE,R0  ;Shift IM=IMAG for lookup,
  1412.                                     ; load lookup table base
  1413.         MOVE    A1,N0               ;Load IM as offset
  1414.         MOVE    Y:RSHFT+3,X1        ;Get shift constant
  1415.         MOVE    X:Y_T,Y0            ;Get Y
  1416.         MPY     Y0,X1,B     X:(R0+N0),A ;Shift Y>>3,
  1417.                                     ; get WI from lookup table
  1418.  
  1419. ;**************************************************************************
  1420. ;       FILTD
  1421. ;
  1422. ; Update of fast quantizer scale factor
  1423. ;
  1424. ; YU(k) = (1 - 2**(-5)) * Y(k) + 2**(-5) * W[I(k)]
  1425. ;
  1426. ; Inputs:
  1427. ;   WI =  siii iiii. | ffff 0000 | 0000 0000  (12TC)
  1428. ;   Y = 0iii i.fff | ffff ff00 | 0000 0000  (13SM)
  1429. ;
  1430. ; Outputs:
  1431. ;   YUT = 0iii i.fff | ffff ff00 | 0000 0000  (13SM)
  1432. ;
  1433. ;**************************************************************************
  1434.  
  1435.         SUB     B,A                 ;Find DIF=WI-Y
  1436.         ASR     A                   ;Find DIFSX=DIF>>5 (actually DIF>>2)
  1437.         ASR     A   Y:(R7)+,X0      ;Get mask K30
  1438.         AND     X0,A                ;Truncate DIFSX
  1439.         ADD     Y0,A    #<$50,X0    ;Find YUT=DIFSX+Y,
  1440.                                     ; get upper limit '10'
  1441.  
  1442. ;**************************************************************************
  1443. ;       LIMB
  1444. ;
  1445. ; Limit quantizer scale factor
  1446. ;
  1447. ; 1.06 <= YU(k) <= 10.00
  1448. ;
  1449. ; Inputs:
  1450. ;   YUT = 0iii i.fff | ffff ff00 | 0000 0000  (13SM)
  1451. ;
  1452. ; Outputs:
  1453. ;   YUP = 0iii i.fff | ffff ff00 | 0000 0000  (13SM)
  1454. ;
  1455. ;**************************************************************************
  1456.  
  1457.         CMP     X0,A    Y:(R7)+,X1  ;Check for YU>10,
  1458.                                     ; get lower limit '1.06' (K31)
  1459.         TGT     X0,A                ;If YU>10 set YU=10
  1460.         CMP     X1,A    Y:YL_T,Y1   ;Check for YU<1.06, get YL
  1461.         TLT     X1,A                ;If YU<1.06 set YU=1.06
  1462.  
  1463. ;**************************************************************************
  1464. ;       FILTE
  1465. ;
  1466. ; Update of slow quantizer scale factor
  1467. ;
  1468. ; YL(k) = (1 - 2**(-6)) * YL(k-1) + 2**(-6) * YU(k)
  1469. ;
  1470. ; Inputs:
  1471. ;   YUP = 0iii i.fff | ffff ff00 | 0000 0000  (13SM)
  1472. ;   YL = 0iii i.fff | ffff ffff | ffff 0000  (19SM)
  1473. ;
  1474. ; Outputs:
  1475. ;   YLP = 0iii i.fff | ffff ffff | ffff 0000  (19SM)
  1476. ;
  1477. ;**************************************************************************
  1478.  
  1479.         TFR     Y1,B    A1,Y:YU_T   ;Move YL, save YUP
  1480.         NEG     B   Y:(R7)+,Y0      ;Find -YL, save YL, get mask K32
  1481.         AND     Y0,B                ;Truncate -YL (-YL>>6)
  1482.         ADD     B,A     Y:RSHFT+6,Y0    ;Find DIF=YUP+(-YL>>6)
  1483.         MOVE    A1,X1
  1484.         MPY     Y0,X1,A             ;Find DIFSX>>6
  1485.         ADD     Y1,A    R2,X:DATAPTR_T  ;Find YLP=DIFSX+YL,
  1486.                                     ; save transmit data pointer
  1487.         MOVE    A1,Y:YL_T           ;Save YL
  1488.  
  1489. ;**************************************************************************
  1490. ;
  1491. ;   Decoder
  1492. ;
  1493. ;**************************************************************************
  1494.  
  1495. DECODE  MOVE    #PP_R,R1            ;Set partial product ptr to WB1
  1496.         MOVE    X:DATAPTR_R,R2      ;Set data pointer to DQ1EXP
  1497.         MOVE    #COEF_R,R6          ;Set coef pointer to B1
  1498.         MOVE    #CONST1,R7          ;Set pointer to misc constants
  1499.  
  1500. ;**************************************************************************
  1501. ;       FMULT
  1502. ;
  1503. ; Multiply predictor coefficients with corresponding
  1504. ;   quantized difference signal or reconstructed signal
  1505. ;
  1506. ;   Data (DQn or SRn) is stored in 11FL format (separate),
  1507. ;   & coefficient (Bn or An) is stored in 16TC format.
  1508. ;
  1509. ; Computes  [An(k-1) * SR(k-n)] or [Bn(k-1) * DQ(k-n)]
  1510. ;
  1511. ; Flow Description:
  1512. ;   1. Convert 16TC An to 13SM AnMAG
  1513. ;   2. Convert 13SM AnMAG to 10FL (AnEXP and AnMANT)
  1514. ;   3. Add SRnEXP to AnEXP to get WAnEXP (5-bits)
  1515. ;   4. Multiply SRnMANT with AnMANT, add '48', and truncate
  1516. ;       to 8-bits to get WAnMANT
  1517. ;   5. Convert 13FL (WAnEXP & WAnMANT) to 15SM WAnMAG
  1518. ;   6. XOR AnS with SRnS to find WAnS
  1519. ;   7. Convert 16SM (WAnMAG & WAnS) to 16TC WAn
  1520. ;
  1521. ; Input:
  1522. ;   SRn = (11FL)
  1523. ;    SRnEXP = X:(R2) = 0000 0000 | 0000 0000 | 0000 eeee
  1524. ;    SRnMANT = X:(R2+1) = 01mm mmm0 | 0000 0000 | 0000 0000
  1525. ;    SRnS = X:(R2+2) = sXXX XXXX | XXXX XXXX | 0000 0000
  1526. ;       (DQ in same format as SR)
  1527. ;
  1528. ;   An = Y:(R6) = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  1529. ;       (Bn in same format as An)
  1530. ;
  1531. ; Output:
  1532. ;   WAn = X:(R1) = siii iiii | iiii iii.f | 0000 0000  (16TC)
  1533. ;       (WBn in same format as WAn)
  1534. ;
  1535. ;**************************************************************************
  1536.  
  1537.         MOVE    #CONST,R0           ;Set pointer to FMULT constants
  1538.         MOVE    #0,Y1
  1539.         DO      #8,ACCUM_R          ;Execute mult 8 times
  1540.  
  1541. ; 1. Convert 16TC An to 13SM AnMAG
  1542.         MOVE    X:(R0)+,X1  Y:(R6),A    ;Get An and mask KF1
  1543.         AND     X1,A    X:(R0)+,X1  ;Truncate An to 13 bits (An>>2),
  1544.                                     ; get mask KF2
  1545.         ABS     A       #$000D,R4   ;Find AnMAG, load
  1546.                                     ; exponent bias (13) into R4
  1547.         AND     X1,A    #<$7E,X1    ;Truncate any ovrflw, get mask
  1548. ;   A1 = 0i.ff ffff | ffff ff00 | 0000 0000 (A2=A0=0)
  1549.  
  1550. ; 2. Convert 13SM AnMAG to 10FL (AnEXP and AnMANT)
  1551.         JNE     <NORMAN_R           ;Test AnMAG
  1552.         MOVE    #<$40,A             ;If AnMAG=0, set AnMANT=1<<5,
  1553.         MOVE    #0,R4               ; and AnEXP=0
  1554.         JMP     <CONTIN_R
  1555. NORMAN_R    NORM    R4,A            ;If AnMAG!=0 do NORM iteration
  1556.         NORM    R4,A                ; 12 times to find MSB
  1557.         NORM    R4,A
  1558.         NORM    R4,A
  1559.         NORM    R4,A
  1560.         NORM    R4,A
  1561.         NORM    R4,A
  1562.         NORM    R4,A
  1563.         NORM    R4,A
  1564.         NORM    R4,A
  1565.         NORM    R4,A
  1566.         NORM    R4,A
  1567. ;   A1 = 01?? ???? | ???? ??00 | 0000 0000 = AnMANT
  1568. ;   R4 = 0000 0000 | 0000 eeee = AnEXP
  1569. CONTIN_R    AND     X1,A    R4,B    ;Truncate AnMANT to 6 bits,
  1570.                                     ; move AnEXP to B
  1571. ;   A1 = 01mm mmm0 | 0000 0000 | 0000 0000 (A2=A0=0)
  1572. ;   B1 = 0000 0000 | 0000 0000 | 0000 eeee (B2=B0=0)
  1573.  
  1574. ; 3. Add SRnEXP to AnEXP to get WAnEXP (5-bits)
  1575.         MOVE    X:(R2)+,X1  A,Y0    ;Get SRnEXP
  1576.         ADD     X1,B    X:(R2)+,X1  ;Find WAnEXP=SRnEXP+AnEXP,
  1577.                                     ; get SRnMANT 
  1578. ;   B1 = 0000 0000 | 0000 0000 | 000e eeee (B2=B0=0)
  1579.  
  1580. ; 4. Multiply SRnMANT with AnMANT, add '48', and truncate
  1581. ;       to 8-bits to get WAnMANT
  1582. ;   Y0 = 01mm mmm0 | 0000 0000 | 0000 0000
  1583. ;   X1 = 01mm mmm0 | 0000 0000 | 0000 0000
  1584.         MPY     Y0,X1,A     X:(R0)+,X0  ;Find WAnMANT, get '48' (KF3)
  1585. ;   A1 = 0mmm mmmm | mmmm m000 | 0000 0000 (A2=A0=0)
  1586. ;   X0 = 0000 0001 | 1000 0000 | 0000 0000 = '48'
  1587.         ADD     X0,A        X:(R0)+,X0  ;Add '48' to WAnMANT, get mask KF4
  1588.         AND     X0,A        X:(R0)+,X0  ;Truncate WAnMANT to 8 bits,
  1589.                                         ; get '26' (KF5)
  1590. ;   A1 = 0mmm mmmm | m000 0000 | 0000 0000 (A2=A0=0)
  1591.  
  1592. ; 5. Convert 13FL (WAnEXP & WAnMANT) to 15SM WAnMAG
  1593. ;   X0 = 0000 0000 | 0000 0000 | 0001 1010 = '26'
  1594. ;   B1 = 0000 0000 | 0000 0000 | 000e eeee (B2=B0=0) 
  1595.         SUB     X0,B    X:(R0)+,X0  ;Find shift offset (WAnEXP-26),
  1596.                                     ; get mask KF6
  1597.         JEQ     <TRUNC_R            ;If offset=26 no shift
  1598.         JMI     <RIGHT_R            ;If offset<26 do right shift
  1599.                                     ;Else offset>26, do left shift
  1600.         REP     B1                  ;Offset>26, shift WAnMANT
  1601.         LSL     A                   ; left up to 4 times
  1602.         JMP     <TRUNC_R
  1603. RIGHT_R ABS     B       #>$0F,Y0    ;Find |offset|, get '15'
  1604.         CMP     Y0,B    B1,N5       ;Compare |offset| to '15',
  1605.                                     ; load offset for shift
  1606.         TGE     Y1,A                ;If |offset|>=15 WAnMAG=0
  1607.         MOVE    A1,X1               ;Move WAnMANT for shift
  1608.         MOVE    Y:(R5+N5),Y0        ;Lookup shift constant
  1609.         MPY     Y0,X1,A             ;Shift WAnMANT right up to 14 times
  1610. ;   A1 = ?mmm mmmm | mmmm mmmm | ???? ???? (A2=A0=0)
  1611. TRUNC_R AND     X0,A    X:(R2)+,X1  Y:(R6)+,B   ;Truncate WAnMAG to 15 bits,
  1612.                                     ; get SRnS & AnS
  1613. ;   A1 = 0iii iiii | iiii iii.f | 0000 0000 (A2=A0=0)
  1614.         NEG     A   A1,X0           ;Find -WAnMAG, save WAnMAG
  1615.  
  1616. ; 6. XOR AnS with SRnS to find WAnS
  1617. ;   B1 = sXXX XXXX | XXXX XXXX | 0000 0000 (B2=sign ext, B0=0)
  1618. ;   X1 = sXXX XXXX | XXXX XXXX | 0000 0000
  1619.         EOR     X1,B    #CONST,R0   ;Find WAnS (in MSB of B),
  1620.                                     ; update pointer to constants
  1621.  
  1622. ; 7. Convert 16SM (WAnMAG & WAnS) to 16TC WAn
  1623.         TPL     X0,A                ;If WAnS=0 use WAnMAG, else use -WAnMAG
  1624. ;   A1 = siii iiii | iiii iii.f | 0000 0000  (A2=sign ext, A0=0)
  1625.         MOVE    A1,X:(R1)+          ;Save WAn
  1626.  
  1627. ;**************************************************************************
  1628. ;       ACCUM
  1629. ;
  1630. ; Add predictor outputs to form the partial signal estimate
  1631. ;   and the signal estimate
  1632. ;
  1633. ; SEZ(k) = [B1(k-1) * DQ(k-1)] + ... + [B6(k-1) * DQ(k-6)]
  1634. ;        = WB1 + WB2 + ... + WB6
  1635. ;
  1636. ; SE(k) = SEZ(k) + [A1(k-1) * SR(k-1)] + [A2(k-1) * SR(k-2)]
  1637. ;       = SEZ + WA1 + WA2
  1638. ;
  1639. ; Inputs:
  1640. ;   WBn & WAn = X:(R1) = siii iiii | iiii iii.f | 0000 0000  (16TC)
  1641. ;
  1642. ; Outputs:
  1643. ;   SEZ = siii iiii | iiii iii.0 | 0000 0000  (15TC)
  1644. ;   SE = siii iiii | iiii iii.0 | 0000 0000  (15TC)
  1645. ;
  1646. ;**************************************************************************
  1647.  
  1648. ACCUM_R MOVE    X:(R1)+,A           ;Get WB1
  1649.         MOVE    X:(R1)+,X0          ;Get WB2
  1650.         ADD     X0,A    X:(R1)+,X0  ;Accumulate WB1&WB2, get WB3
  1651.         ADD     X0,A    X:(R1)+,X0  ;Accumulate WB3, get WB4
  1652.         ADD     X0,A    X:(R1)+,X0  ;Accumulate WB4, get WB5
  1653.         ADD     X0,A    X:(R1)+,X0  ;Accumulate WB5, get WB6
  1654.         ADD     X0,A    X:(R1)+,X0  ;Accumulate WB6 to get SEZI, get WA1
  1655.         TFR     A,B     Y:(R7)+,X1  ;Copy SEZI, get mask K1
  1656.         AND     X1,B    X:AP_R,Y0   ;Truncate SEZI, get AP
  1657.         ADD     X0,A    X:(R1)+,X0  ;Accumulate WA1, get WA2
  1658.         ADD     X0,A    B1,Y:SEZ_R  ;Accumulate WA2 to get SEI, save SEZ
  1659.         AND     X1,A    #<$20,X0    ;Truncate SEI, get '1'
  1660.         TFR     Y0,A    A1,Y:SE_R   ;Move AP, save SE
  1661.  
  1662. ;**************************************************************************
  1663. ;       LIMA
  1664. ;
  1665. ; Limit speed control parameter
  1666. ;
  1667. ; AL(k) = 1        if AP(k-1) > 1
  1668. ;       = AP(k-1)  if AP(k-1) <= 1
  1669. ;
  1670. ; Inputs:
  1671. ;   AP = 0ii.f ffff | fff0 0000 | 0000 0000  (10SM)
  1672. ;
  1673. ; Outputs:
  1674. ;   AL = 0i.ff ffff | 0000 0000 | 0000 0000  (7SM)
  1675. ;
  1676. ;**************************************************************************
  1677.  
  1678.         CMP     X0,A    Y:YL_R,B    ;Test AP, get YL
  1679.         TGT     X0,A                ;If AP>'1' set AL='1'
  1680.         LSL     A       #<$7F,X0    ;Shift to align radix pt., get mask
  1681.         AND     X0,A    Y:(R7)+,X0  ;Truncate AL (AP>>2), get mask K2
  1682.  
  1683. ;**************************************************************************
  1684. ;       MIX
  1685. ;
  1686. ; Form linear combination of fast and slow quantizer
  1687. ;   scale factors
  1688. ;
  1689. ; Y(k) = AL(k) * YU(k-1) + [1 - AL(k)] * YL(k-1)
  1690. ;
  1691. ; Inputs:
  1692. ;   YL = 0iii i.fff | ffff ffff | ffff 0000  (19SM)
  1693. ;   AL = 0i.ff ffff | 0000 0000 | 0000 0000  (7SM)
  1694. ;   YU = 0iii i.fff | ffff ff00 | 0000 0000  (13SM)
  1695. ;
  1696. ; Outputs:
  1697. ;   Y = 0iii i.fff | ffff ff00 | 0000 0000  (13SM)
  1698. ;
  1699. ;**************************************************************************
  1700.  
  1701.         AND     X0,B    A,X0    Y:YU_R,A    ;Truncate YL (YL>>6), get YU
  1702.         SUB     B,A     B,Y1    X0,X:AL_R   ;Find DIF=YU-YL, save YL, get AL
  1703.         ABS     A       A,B         ;Find DIFM=|DIF|, save DIFS
  1704.         MOVE    A1,Y0
  1705.         MPY     X0,Y0,A     Y:(R7)+,X0  ;Find DIFM*AL, get mask K3
  1706.         AND     X0,A                ;Truncate to find PRODM=(DIFM*AL)>>6
  1707.         NEG     A   A1,X0           ;Find -PRODM, save PRODM
  1708.         TST     B                   ;Check DIFS
  1709.         TPL     X0,A                ;If DIFS=0 PROD=PRODM,
  1710.                                     ; else PROD=-PRODM
  1711.         ASL     A   Y1,B            ;Line up radix point
  1712.         ADD     Y1,A                ;Find Y=PROD+(YL>>6)
  1713.         MOVE    A,X:Y_R             ;Save Y
  1714.  
  1715. ;**************************************************************************
  1716. ;
  1717. ; Input ADPCM data (I) here. For simulation purposes the Input 
  1718. ; Word from File subroutine on the 56001 ADS board is used.
  1719. ;
  1720. ;**************************************************************************
  1721.  
  1722.         MOVE    #2,X0               ;Input ADPCM word (I)
  1723.         JSR     $E002
  1724.  
  1725. ;**************************************************************************
  1726. ;       RECONST
  1727. ;
  1728. ; Reconstruct quantized difference signal in the log domain
  1729. ;
  1730. ;     |I(k)| | log2|DQ(k)| - Y(k)
  1731. ;    --------+-------------------
  1732. ;       7    |      3.32
  1733. ;       6    |      2.91
  1734. ;       5    |      2.52
  1735. ;       4    |      2.13
  1736. ;       3    |      1.66
  1737. ;       2    |      1.05
  1738. ;       1    |      0.031
  1739. ;       0    |      - inf
  1740. ;
  1741. ; Inputs:
  1742. ;   I = iiii 0000 | 0000 0000 | 0000 0000  (ADPCM format)
  1743. ;
  1744. ; Output:
  1745. ;   DQLN = siii i.fff | ffff 0000 | 0000 0000  (12TC)
  1746. ;   DQS = sXXX 0000 | 0000 0000 | 0000 0000  (1TC)
  1747. ;
  1748. ;**************************************************************************
  1749.  
  1750.         MOVE    #<$F0,X1
  1751.         MOVE    A,Y1    A,X:I_R     ;Save DQS (sign of I) to Y1
  1752.         EOR     X1,A    Y:RSHFT+20,Y0   ;Invert bits of I
  1753.         TMI     Y1,A                ;If ^IS=1, use I, else use ^I
  1754. ;   A1 = 0iii 0000 | 0000 0000 | 0000 0000 (A2=?, A0=0)
  1755.         MOVE    A1,X0
  1756.         MOVE    A1,X:IMAG           ;Save |I|
  1757.         MPY     X0,Y0,A     #IQUANTAB,R4    ;Shift IMAG>>20
  1758. ;   A1 = 0000 0000 | 0000 0000 | 0000 0iii (A2=A0=0)
  1759.         MOVE    A1,N4               ;Load IMAG as offset
  1760.         MOVE    X:Y_R,B             ; into IQUAN table, get Y
  1761.         MOVE    #CONST8,R7          ;Adjust constant pointer
  1762.         MOVE    X:(R4+N4),A         ;Lookup DQLN
  1763.  
  1764. ;**************************************************************************
  1765. ;       ADDA
  1766. ;
  1767. ; Add scale factor to log version of quantized difference
  1768. ;   signal
  1769. ;
  1770. ; DQL = DQLN + Y
  1771. ;
  1772. ; Inputs:
  1773. ;   Y = 0iii i.fff | ffff ff00 | 0000 0000  (13SM)
  1774. ;   DQLN = siii i.fff | ffff 0000 | 0000 0000  (12TC)
  1775. ;
  1776. ; Output:
  1777. ;   DQL = siii i.fff | ffff 0000 | 0000 0000  (12TC)
  1778. ;
  1779. ;**************************************************************************
  1780.  
  1781.         MOVE    Y:(R7)+,Y0          ;Get mask K8 for ADDA
  1782.         AND     Y0,B    Y:(R7)+,X0  ;Truncate Y to 11 bits (Y<<2),
  1783.                                     ; get mask K9
  1784.         ADD     B,A     #<$08,X1    ;Find DQL=DQLN+(Y<<2), get '1'
  1785.    
  1786. ;**************************************************************************
  1787. ;       ANTILOG
  1788. ;
  1789. ; Convert quantized difference signal from log to linear
  1790. ;   domain
  1791. ;
  1792. ; Input:
  1793. ;   DQL = siii i.fff | ffff 0000 | 0000 0000  (12TC)
  1794. ;   DQS = sXXX 0000 | 0000 0000 | 0000 0000  (1TC)
  1795. ;
  1796. ; Outputs:
  1797. ;   DQ = siii iiii | iiii iii.0 | 0000 0000  (15SM)
  1798. ;
  1799. ;**************************************************************************
  1800.  
  1801.         JPL     <CONVLOG_R          ;If DQL>=0 (DS=0) convert DQL,
  1802.                                     ; else DQL<0 (DS=1), set |DQ|=0
  1803.         TFR     Y1,A    #<$80,X0    ;Get DQS (MSB of I), get mask
  1804.         AND     X0,A    #0,B        ;Mask off DQS, set |DQ|=0
  1805. ;   A1 = s000 0000 | 0000 0000 | 0000 0000  (A2=sign ext, A0=0)
  1806.         MOVE    B1,Y:DQMAG          ;Save DQMAG=|DQ|
  1807.         MOVE    (R7)+               ;Adjust constant pointer
  1808.         MOVE    (R7)+
  1809.         JMP     <SAVEDQ_R
  1810.  
  1811. CONVLOG_R   AND     X0,A    A,B     ;Find fractional part (DMN),
  1812.                                     ; save DS
  1813. ;   A1 = 0000 0.fff | ffff 0000 | 0000 0000  (A2=A0=0)
  1814.         OR      X1,A    #<$78,X0    ;Add implied '1' to DMN to
  1815.                                     ; find DQT, get integer mask
  1816. ;   A1 = 0000 1.fff | ffff 0000 | 0000 0000  (A2=A0=0)
  1817.         AND     X0,B    Y:RSHFT+19,Y0   ;Find integer part (DEX),
  1818.                                     ; get shift constant
  1819. ;   B1 = 0iii i.000 | 0000 0000 | 0000 0000  (B2=B0=0)
  1820.         MOVE    B1,X0
  1821.         MPY     X0,Y0,B     Y:(R7)+,X0  ;Shift DEX>>19, get '10' (K10)
  1822. ;   A1 = 0000 1.fff | ffff 0000 | 0000 0000  (A2=A0=0)
  1823. ;   B1 = 0000 0000 | 0000 0000 | 0000 iiii.  (B2=B0=0)
  1824.         SUB     X0,B    Y:(R7)+,X0  ;Find DQT shift=DEX-'10',
  1825.                                     ; get mask K11
  1826.         JEQ     <TRUNCDQM_R         ;If DEX=10, no shift
  1827.         JLT     <SHFRDQ_R           ;If DEX<10, shift right
  1828.         REP     B1                  ;Else shift DQT left
  1829.         LSL     A                   ; up to 4 times
  1830.         JMP     <TRUNCDQM_R
  1831.  
  1832. SHFRDQ_R    NEG     B               ;Find 10-DEX
  1833.         MOVE    B1,N5               ;Use 10-DEX for shift lookup
  1834.         MOVE    A1,Y0
  1835.         MOVE    Y:(R5+N5),X1        ;Lookup shift constant
  1836.         MPY     X1,Y0,A             ;Shift DQT right up to 9 times
  1837. TRUNCDQM_R  AND     X0,A    #<$80,B ;Truncate to find DQMAG=|DQ|,
  1838.                                     ; get sign mask
  1839. ;   A1 = 0iii iiii | iiii iii.0 | 0000 0000  (A2=A0=0)
  1840.         AND     Y1,B    A1,Y:DQMAG  ;Mask off DQS, save DQMAG           
  1841. ;   B1 = s000 0000 | 0000 0000 | 0000 0000  (B2=?, B0=0)
  1842.         MOVE    B1,X0
  1843.         OR      X0,A                ;Add DQS to DQMAG to get DQ
  1844. ;   A1 = siii iiii | iiii iii.0 | 0000 0000  (A2=?, A0=0)
  1845. SAVEDQ_R    MOVE    A1,X:DQ_R       ;Save DQ
  1846.  
  1847. ;**************************************************************************
  1848. ;       TRANS
  1849. ;
  1850. ; Transition detector
  1851. ;
  1852. ; TR(k) = 1 if TD(k)=1 and |DQ(k)|> 24 x 2**(YL(k))
  1853. ;         0 otherwise
  1854. ;
  1855. ; Inputs:
  1856. ;   TD = i000 0000 | 0000 0000 | 0000 0000  (1TC)
  1857. ;   YL = 0iii i.fff | ffff ffff | ffff 0000  (19SM)
  1858. ;   DQ = siii iiii | iiii iii.0 | 0000 0000  (15SM)
  1859. ;
  1860. ; Output:
  1861. ;   TR = i000 0000 | 0000 0000 | 0000 0000  (1TC)
  1862. ;
  1863. ;**************************************************************************
  1864.  
  1865.         MOVE    Y:TD_R,A            ;Get TD
  1866.         TST     A   #0,A            ;Check TD, set TR=0
  1867.         JEQ     <SAVETR_R           ;If TD=0 save TR=0
  1868.                                     ; else test DQ and YL
  1869.         MOVE    Y:YL_R,A            ;Get YL
  1870.         TFR     A,B     Y:(R7)+,X0  ;Save YL, get mask K12
  1871.         AND     X0,A    #<$08,X0    ;Find YLFRAC (YL>>10), get '1'
  1872.         OR      X0,A    B,X1    Y:(R7)+,Y1  ;Add implied '1' to YLFRAC,
  1873.                                     ; get mask K13
  1874.         MPY     Y1,X1,B     Y:(R7)+,X0  ;Find YLINT=YL>>15, get '8' (K14)
  1875.         MOVE    B1,B                ;Adjust sign extension
  1876.         CMP     X0,B    Y:(R7)+,X0  ;Compare YLINT to '8', get '5' (K15)
  1877.         JGT     <MAXTHR_R           ;If YLINT>8 set maximum THR2
  1878.         SUB     X0,B                ;Find YLINT-5
  1879.         JEQ     <SETDQTHR_R         ;If YLINT=5 don't shift
  1880.         JLT     <RSHFT_R            ;If YLINT<5 shift right
  1881.  
  1882.         REP     B1                  ;Else shift YLFRAC left
  1883.         LSL     A                   ; up to 3 times to get THR1
  1884.         JMP     <SETDQTHR_R
  1885.  
  1886. MAXTHR_R    MOVE    #<$7C,A         ;Set maximum THR2 (31<<9)
  1887.         JMP     <SETDQTHR_R
  1888.  
  1889. RSHFT_R NEG     B                   ;Find 5-YLINT
  1890.         MOVE    B1,N5               ;Use 5-YLINT for shift lookup
  1891.         MOVE    A1,X0
  1892.         MOVE    Y:(R5+N5),X1        ;Lookup shift constant
  1893.         MPY     X0,X1,A             ;Shift YLFRAC right up to ? times
  1894.                                     ; to get THR1
  1895. SETDQTHR_R  TFR     A,B     Y:(R7)+,X0  ;Get mask K16
  1896.         LSR     B                   ;Find THR2>>1
  1897.         AND     X0,B                ;Truncate THR2>>1
  1898.         ADD     B,A     #0,X1       ;Find THR2+(THR2>>1)
  1899.         LSR     A                   ;Find (THR2+(THR2>>1)>>1
  1900.         AND     X0,A    Y:DQMAG,X0  ;Truncate to find DQTHR, get DQMAG
  1901.         CMP     X0,A    #<$80,A     ;Compare DQMAG to DQTHR, set TR=1
  1902.         TGT     X1,A                ;If DQMAG>DQTHR leave TR=1,
  1903.                                     ; else DQMAG<=DQTHR, set TR=0
  1904. SAVETR_R    MOVE    A1,Y:TR_R       ;Save TR
  1905.  
  1906. ;**************************************************************************
  1907. ;       ADDB
  1908. ;
  1909. ; Add quantized difference signal and signal estimate
  1910. ;   to form reconstructed signal
  1911. ;
  1912. ; SR(k-n) = SE(k-n) + DQ(k-n)
  1913. ;
  1914. ; Inputs:
  1915. ;   DQ = siii iiii | iiii iii.0 | 0000 0000  (15SM)
  1916. ;   SE = siii iiii | iiii iii.0 | 0000 0000  (15TC)
  1917. ;
  1918. ; Output:
  1919. ;   SR = siii iiii | iiii iiii. | 0000 0000  (16TC)
  1920. ;
  1921. ;**************************************************************************
  1922.  
  1923.         MOVE    Y:SE_R,B            ;Get SE
  1924.         ASR     B   X:DQ_R,A        ;Sign extend SE to get SEI, get DQS
  1925.         TST     A       Y:DQMAG,A   ;Check DQS, get DQMAG
  1926.         JPL     <SHFTDQ_R           ;If DQS=0 continue
  1927.         NEG     A                   ;Convert DQ to 2's comp
  1928. SHFTDQ_R    ASR     A               ;Sign extend DQ to get DQI
  1929.         ADD     A,B     #CONST17,R7 ;Find SR=DQ+SE, update const pointer
  1930.  
  1931. ;**************************************************************************
  1932. ;       ADDC
  1933. ;
  1934. ; Obtain sign of addition of the quantized difference
  1935. ;   signal and the partial signal estimate
  1936. ;
  1937. ; P(k) = DQ(k) + SEZ(k)
  1938. ; PK0 = sign of P(k)
  1939. ;
  1940. ; Inputs:
  1941. ;   DQ = siii iiii | iiii iii.0 | 0000 0000  (15SM)
  1942. ;   SEZ = siii iiii | iiii iii.0 | 0000 0000 (15TC)
  1943. ;
  1944. ; Output:
  1945. ;   PK0 = sXXX XXXX | XXXX XXXX | 0000 0000  (1TC)
  1946. ;   SIGPK = i000 0000 | 0000 0000 | 0000 0000  (1TC)
  1947. ;
  1948. ;**************************************************************************
  1949.  
  1950.         MOVE    B1,Y:SR_R           ;Save SR
  1951.         MOVE    Y:SEZ_R,B           ;Get SEZ
  1952.         ASR     B                   ;Sign extend SEZ to SEZI
  1953.         ADD     B,A     #0,B        ;Find DQSEZ=DQ+SEZ,
  1954.                                     ; set SIGPK=0
  1955.         TST     A   #<$80,X0        ;Check DQSEZ, get '1'
  1956.         TEQ     X0,B                ;If DQSEZ=0, SIGPK=1,
  1957.                                     ; else SIGPK=0
  1958.  
  1959.         MOVE    Y:PK1_R,X0
  1960.         MOVE    X0,Y:PK2_R          ;Delay previous PK1
  1961.         MOVE    Y:PK0_R,X0
  1962.         MOVE    X0,Y:PK1_R          ;Delay previous PK0
  1963.         MOVE    A1,Y:PK0_R          ;Save new PK0
  1964.         MOVE    B1,Y:SIGPK_R        ;Save SIGPK
  1965.         EOR     X0,A    Y:PK2_R,X0  ;Find PKS1=PK0**PK1
  1966.                                     ; for UPA1 & UPA2
  1967.         MOVE    A1,X:PKS1           ;Save PKS1
  1968.         MOVE    Y:PK0_R,A
  1969.         EOR     X0,A    #3,N2       ;Find PKS2=PK0**PK2 for UPA2
  1970.         MOVE    A1,X:PKS2           ;Save PKS2
  1971.         MOVE    (R2)+               ;Adjust data buffer pointer so
  1972.         MOVE    (R2)+               ; that R2 points to DQ1S
  1973.  
  1974. ;**************************************************************************
  1975. ;       XOR
  1976. ;
  1977. ; Find one bit "exclusive or" of the sign of difference
  1978. ;   signal and the sign of delayed difference signal.
  1979. ;
  1980. ; Un = sgn[DQ(k)] XOR sgn[DQ(k-n)]
  1981. ;
  1982. ; Inputs:
  1983. ;   DQ = siii iiii | iiii iii.0 | 0000 0000 (15SM)
  1984. ;   DQnS = X:(R2+n) sXXX XXXX | XXXX XXXX | 0000 0000
  1985. ;
  1986. ; Outputs:
  1987. ;   Un = sXXX XXXX | XXXX XXXX | 0000 0000 (1TC)
  1988. ;
  1989. ;**************************************************************************
  1990. ;**************************************************************************
  1991. ;       UPB
  1992. ;
  1993. ; Update the coefficients of the sixth order predictor
  1994. ;
  1995. ; Bn(k) = [1-(2**-8)] * Bn(k-1)
  1996. ;           + (2**-7) * sgn[DQ(k)] * sgn[DQ(k-n)]
  1997. ;
  1998. ; Inputs:
  1999. ;   Bn = Y:(R6+n) = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  2000. ;   DQ = siii iiii | iiii iii.0 | 0000 0000 (15SM)
  2001. ;   Un = sXXX XXXX | XXXX XXXX | 0000 0000 (1TC)
  2002. ;
  2003. ; Outputs:
  2004. ;   BnP = Y:(R6+n) = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  2005. ;
  2006. ;**************************************************************************
  2007.  
  2008.         MOVE    Y:DQMAG,A           ;Get DQMAG
  2009.         TST     A   X:DQ_R,Y0       ;Check DQMAG, get DQS
  2010.         JNE     <XORUPB_R           ;If DQMAG!=0 use section with XOR,
  2011.                                     ; else use section with no XOR
  2012.                                     ; (because UGBn=0 if DQMAG=0)
  2013.  
  2014. ; UPB without XOR
  2015.         MOVE    Y:RSHFT+8,X1        ;Get shift constant
  2016.         MOVE    (R7)+               ;Adjust constant pointer
  2017.         MOVE    (R7)+
  2018.         MOVE    Y:(R7)+,X0          ;Get mask K19
  2019.         DO      #6,ENDLOOP_R        ;Do UPB for B1-B6
  2020.         MOVE    X:(R2)+N2,A     Y:(R6),Y1   ;Get Bn (& DQnS but don't use)
  2021.         MPY     X1,Y1,A             ;Find Bn>>8
  2022.         AND     X0,A                ;Truncate (Bn>>8)
  2023.         NEG     A                   ;Find UBn=ULBn=-(Bn>>8)
  2024.         ADD     Y1,A                ;Find BnP=Bn+UBn
  2025.         MOVE    A1,Y:(R6)+          ;Store BnP to Bn
  2026. ENDLOOP_R   JMP     <UPA2_R
  2027.  
  2028. ; UPB with XOR
  2029. XORUPB_R    MOVE    Y:(R7)+,X0      ;Get +gain (K17)
  2030.         DO      #6,UPTR_R           ;Do UPB and XOR for B1-B6
  2031.         MOVE    X:(R2)+N2,A     Y:(R6),Y1   ;Get Bn & DQnS
  2032.         EOR     Y0,A    Y:(R7)+,X1  ;Find Un=DQS**DQnS (XOR),
  2033.                                     ; get -gain (K18)
  2034.         TPL     X0,A                ;If Un=0 set UGBn=+gain
  2035.         TMI     X1,A                ;If Un=1 set UGBn=-gain
  2036.         MOVE    Y:RSHFT+8,X1        ;Get shift constant
  2037.         MPY     X1,Y1,B     Y:(R7)-,X1  ;Shift Bn>>8, get mask K19
  2038.         AND     X1,B                ;Truncate (Bn>>8)
  2039.         NEG     B                   ;Find ULBn=-(Bn>>8)
  2040.         ADD     B,A                 ;Find UBn=UGBn+ULBn
  2041.         ADD     Y1,A                ;Find BnP=Bn+UBn
  2042.         MOVE    A1,Y:(R6)+          ;Store BnP to Bn
  2043. UPTR_R  MOVE    (R7)+               ;Adjust constant pointer
  2044.         MOVE    (R7)+
  2045.  
  2046. ;**************************************************************************
  2047. ;       UPA2
  2048. ;
  2049. ; Update the A2 coefficient of the second order predictor.
  2050. ;
  2051. ; A2(k) = [1-(2**-7)] * A2(k-1)
  2052. ;           + (2**-7) * { sgn[P(k)] * sgn[P(k-2)]
  2053. ;               - F[A1(k-1)] * sgn[P(k)] * sgn[P(k-1)] }
  2054. ;
  2055. ; F[A1(k)] = 4 * A1       if |A1|<=(2**-1)
  2056. ;          = 2 * sgn(A1)  if |A1|>(2**-1)
  2057. ;
  2058. ; Inputs:
  2059. ;   A1 = Y:(R6) = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  2060. ;   A2 = Y:(R6+1) = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  2061. ;   SIGPK = i000 0000 | 0000 0000 | 0000 0000  (1TC)
  2062. ;   PK0 = sXXX XXXX | XXXX XXXX | 0000 0000  (1TC)
  2063. ;   PK1 = sXXX XXXX | XXXX XXXX | 0000 0000  (1TC)
  2064. ;   PK2 = sXXX XXXX | XXXX XXXX | 0000 0000  (1TC)
  2065. ;     (Note: PKS1 & PKS2 have been previously calculated)
  2066. ;
  2067. ; Outputs:
  2068. ;   A2T = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  2069. ;
  2070. ;**************************************************************************
  2071.  
  2072. UPA2_R  MOVE    X:PKS2,A            ;Get PKS2=PK0**PK2
  2073.         TST     A   #<$10,Y0        ;Check PKS2, get '+1'
  2074.         MOVE    #<$F0,Y1            ;Get '-1'
  2075.         TPL     Y0,A                ;If PKS2=0, set UGA2A='+1'
  2076.         TMI     Y1,A                ;If PKS2=1, set UGA2A='-1'
  2077.         MOVE    A,X1    Y:(R6)+,A   ;Save UGA2A, get A1
  2078.         MOVE    Y:(R7)+,Y0          ;Get '+1.99' (K20)
  2079.         CMP     Y0,A    Y:(R7)+,Y1  ;Check A1, get '-1.99' (K21)
  2080.         TGT     Y0,A                ;If A1>=1/2, set FA1='1.99'
  2081.         CMP     Y1,A    X:PKS1,B    ;Check A1 again, get PKS1=PK0**PK1
  2082.         TLT     Y1,A                ;If A1<=-1/2, set FA1='-1.99'
  2083.         TST     B       #0,X0       ;Check PKS1
  2084.         JMI     <FINDSUM_R          ;If PKS1=1, FA=FA1
  2085.         NEG     A                   ; else PKS1=0, set FA=-FA1
  2086. FINDSUM_R   ADD     X1,A    Y:RSHFT+5,Y1    ;Find UGA2B=UGA2A+FA,
  2087.                                     ; get shift constant
  2088.         MOVE    A,X1
  2089.         MPY     X1,Y1,A     Y:(R7)+,X1  ;Find UGA2B>>7, get mask K22
  2090.         AND     X1,A    Y:SIGPK_R,B ;Truncate UGA2, get SIGPK
  2091.         TST     B   Y:(R6),Y0       ;Check SIGPK, get A2
  2092.         TMI     X0,A                ;If SIGPK=1, set UGA2=0
  2093.         MOVE    Y:RSHFT+7,X0        ;Get shift constant
  2094.         MPY     Y0,X0,B             ;Find A2>>7
  2095.         AND     X1,B                ;Truncate to find A2>>7
  2096.         NEG     B       #<$D0,X0    ;Find ULA2=-(A2>>7), get A2LL
  2097.         ADD     B,A     #<$30,X1    ;Find UA2=UGA2+ULA2, get A2UL
  2098.         ADD     Y0,A    Y:(R7)+,Y1  ;Find A2T=A2+UA2, get -gain (K23)
  2099.  
  2100. ;**************************************************************************
  2101. ;       LIMC
  2102. ;
  2103. ; Limit the A2 coefficient of the second order predictor.
  2104. ;
  2105. ;   |A2(k)| <= '0.75' 
  2106. ;
  2107. ; Inputs:
  2108. ;   A2T = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  2109. ;
  2110. ; Outputs:
  2111. ;   A2P = Y:(R6) = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  2112. ;
  2113. ;**************************************************************************
  2114.  
  2115.         CMP     X0,A    Y:(R7)+,Y0  ;Check A2P, get +gain (K24)
  2116.         TLT     X0,A                ;If A2P<-0.75, set A2P=-0.75
  2117.         CMP     X1,A    X:PKS1,B    ;Check A2P again, get PKS1=PK0**PK1
  2118.         TGT     X1,A                ;If A2P>0.75, set A2P=0.75
  2119.         MOVE    A,Y:A2P_R           ;Save A2P
  2120.         MOVE    A,Y:(R6)-           ;Save A2P to A2
  2121.  
  2122. ;**************************************************************************
  2123. ;       UPA1
  2124. ;
  2125. ; Update the A1 coefficient of the second order predictor.
  2126. ;
  2127. ; A1(k) = [1-(2**-8)] * A1(k-1)
  2128. ;           + 3 * (2**-8) * sgn[P(k)] * sgn[P(k-1)]
  2129. ;
  2130. ; Inputs:
  2131. ;   A1 = Y:(R6) = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  2132. ;   SIGPK = Y:(R0) = i000 0000 | 0000 0000 | 0000 0000  (1TC)
  2133. ;   PK0 = sXXX XXXX | XXXX XXXX | 0000 0000  (1TC)
  2134. ;   PK1 = sXXX XXXX | XXXX XXXX | 0000 0000  (1TC)
  2135. ;     (Note: PKS1 has been previously calculated)
  2136. ;
  2137. ; Outputs:
  2138. ;   A1T = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  2139. ;
  2140. ;**************************************************************************
  2141.  
  2142.         TST     B       Y:SIGPK_R,B ;Check PKS1, get SIGPK
  2143.         TPL     Y0,A                ;If PKS=0, set UGA1=+gain
  2144.         TMI     Y1,A                ;If PKS=1, set UGA1=-gain
  2145.         TST     B       #0,X0       ;Check SIGPK
  2146.         TMI     X0,A                ;If SIGPK=1, set UGA1=0
  2147.         MOVE    Y:(R6),X1           ;Get A1
  2148.         MOVE    Y:RSHFT+8,Y0        ;Get shift constant
  2149.         MPY     Y0,X1,B     Y:(R7)+,X0  ;Find A1>>8, get mask K25
  2150.         AND     X0,B                ;Truncate (A1>>8)
  2151.         NEG     B                   ;Find ULA1=-(A1>>8)
  2152.         ADD     B,A     #<$3C,B     ;Find UA1=UGA1+ULA1,
  2153.                                     ; get OME='1-(2**-4)'
  2154.         ADD     X1,A    Y:A2P_R,X0  ;Find A1T=A1+UA1, get A2P
  2155.  
  2156. ;**************************************************************************
  2157. ;       LIMD
  2158. ;
  2159. ; Limit the A1 coefficient of the second order predictor.
  2160. ;
  2161. ;   |A1(k)| <= [1-(2**-4)] - A2(k)
  2162. ;
  2163. ; Inputs:
  2164. ;   A1T = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  2165. ;   A2P = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  2166. ;
  2167. ; Outputs:
  2168. ;   A1P = Y:(R6) = si.ff ffff | ffff ffff | 0000 0000 (16TC)
  2169. ;
  2170. ;**************************************************************************
  2171.  
  2172.         SUB     X0,B                ;Find A1UL=OME-A2P
  2173.         CMP     B,A     B,X0        ;Check A1T
  2174.         TGT     X0,A                ;If A1T>A1UL, set A1P=A1UL
  2175.         NEG     B       (R2)+       ;Find A1LL=-A1UL=A2P-OME
  2176.         CMP     B,A     B,X0        ;Check A1T again
  2177.         TLT     X0,A                ;If A1T<A1LL, set A1P=A1LL
  2178.         MOVE    A1,Y:(R6)+          ;Store A1P to A1
  2179.         MOVE    (R6)+               ;Adjust coef pointer
  2180.  
  2181. ;**************************************************************************
  2182. ;       FLOATA
  2183. ;
  2184. ; Converts the quantized difference signal from 15-bit
  2185. ;   signed magnitude to floating pt. format (11FL - sign,
  2186. ;   exp, and mant stored separately)
  2187. ;
  2188. ; Inputs:
  2189. ;   DQ = siii iiii | iiii iii.0 | 0000 0000 (15SM)
  2190. ;
  2191. ; Outputs:
  2192. ;   DQ0 = (11FL)
  2193. ;    DQ0EXP = X:(R2) = 0000 0000 | 0000 0000 | 0000 eeee
  2194. ;    DQ0MANT = X:(R2+1) = 01mm mmm0 | 0000 0000 | 0000 0000
  2195. ;    DQ0S = X:(R2+2) = sXXX XXXX | XXXX XXXX | 0000 0000
  2196. ;
  2197. ;**************************************************************************
  2198.  
  2199.         MOVE    X:DQ_R,Y0           ;Get DQS
  2200.         MOVE    Y:DQMAG,A           ;Get MAG=DQMAG
  2201.         TST     A   #$000E,R0       ;Check MAG, get exponent bias (14)
  2202.         JNE     <NORMDQ_R           ;Test MAG
  2203.         MOVE    #<$40,A             ;If MAG=0 set MANT=100000,
  2204.         MOVE    #0,R0               ; and EXP=0
  2205.         JMP     <TRUNCDQ_R
  2206. NORMDQ_R    NORM    R0,A            ;If MAG!=0 do NORM iteration 13
  2207.         NORM    R0,A                ; times to find MSB of MAG
  2208.         NORM    R0,A
  2209.         NORM    R0,A
  2210.         NORM    R0,A
  2211.         NORM    R0,A
  2212.         NORM    R0,A
  2213.         NORM    R0,A
  2214.         NORM    R0,A
  2215.         NORM    R0,A
  2216.         NORM    R0,A
  2217.         NORM    R0,A
  2218.         NORM    R0,A
  2219. ;   A1 = 01?? ???? | ???? ???0 | 0000 0000 = normalized MAG (A2=A0=0)
  2220. ;   R0 = 0000 0000 | 0000 eeee = exponent of normalized MAG
  2221.  
  2222. TRUNCDQ_R   MOVE    #<$7E,X0        ;Get mask
  2223.         AND     X0,A    R0,X:(R2)+  ;Truncate MANT to 6 bits,
  2224.                                     ; save EXP to DQ1EXP
  2225. ;   A1 = 01mm mmm0 | 0000 0000 | 0000 0000  (A2=A0=0)
  2226.         MOVE    A1,X:(R2)+          ;Save MANT to DQ1MANT
  2227.         MOVE    Y0,X:(R2)+          ;Save DQ to DQ1S
  2228.  
  2229. ;**************************************************************************
  2230. ;       FLOATB
  2231. ;
  2232. ; Converts the reconstructed signal from 16-bit two's 
  2233. ;   complement to floating pt. format (11FL - sign,
  2234. ;   exp, and mant stored separately)
  2235. ;
  2236. ; Inputs:
  2237. ;   SR = siii iiii | iiii iiii. | 0000 0000  (16TC)
  2238. ;
  2239. ; Outputs:
  2240. ;   SR0 = (11FL)
  2241. ;    SR0EXP = X:(R2) = 0000 0000 | 0000 0000 | 0000 eeee
  2242. ;    SR0MANT = X:(R2+1) = 01mm mmm0 | 0000 0000 | 0000 0000
  2243. ;    SR0S = X:(R2+2) = sXXX XXXX | XXXX XXXX | 0000 0000
  2244. ;
  2245. ;**************************************************************************
  2246.  
  2247.         MOVE    #15,N2
  2248.         MOVE    Y:SR_R,B            ;Get SR
  2249.         MOVE    (R2)+N2             ;Adjust data pointer
  2250.         ABS     B       B,Y0        ;Find MAG=|SR|, save SRS
  2251.         TST     B   #$000F,R0       ;Load exponent bias
  2252.         JNE     <NORMSR_R           ;Test MAG
  2253.         MOVE    #<$40,B             ;If MAG=0 set MANT=100000,
  2254.         MOVE    #0,R0               ; and EXP=0
  2255.         JMP     <TRUNCSR_R
  2256. NORMSR_R    NORM    R0,B            ;If MAG!=0 do NORM iteration 14
  2257.         NORM    R0,B                ; times to find MSB of MAG
  2258.         NORM    R0,B
  2259.         NORM    R0,B
  2260.         NORM    R0,B
  2261.         NORM    R0,B
  2262.         NORM    R0,B
  2263.         NORM    R0,B
  2264.         NORM    R0,B
  2265.         NORM    R0,B
  2266.         NORM    R0,B
  2267.         NORM    R0,B
  2268.         NORM    R0,B
  2269.         NORM    R0,B
  2270. ;   A1 = 01?? ???? | ???? ???0 | 0000 0000 = normalized MAG (A2=A0=0)
  2271. ;   R0 = 0000 0000 | 0000 eeee = exponent of normalized MAG
  2272.  
  2273. TRUNCSR_R   AND     X0,B    R0,X:(R2)+  ;Truncate MANT to 6 bits,
  2274.                                     ; save EXP to SR1EXP
  2275. ;   A1 = 01mm mmm0 | 0000 0000 | 0000 0000  (A2=A0=0)
  2276.         MOVE    B1,X:(R2)+          ;Save MANT to SR1MANT
  2277.         MOVE    Y0,X:(R2)+          ;Save SR to SR1S
  2278.         MOVE    #3,N2
  2279.         MOVE    Y:A2P_R,B           ;Get A2P
  2280.         MOVE    (R2)+N2             ;Adjust data pointer
  2281.  
  2282. ;**************************************************************************
  2283. ;       TONE
  2284. ;
  2285. ; Partial band signal detection
  2286. ;
  2287. ; TD(k) = 1 if A2(k) < -0.71875
  2288. ;         0 otherwise
  2289. ;
  2290. ; Inputs:
  2291. ;   A2P = si.ff ffff | ffff ffff | 0000 0000  (16TC)
  2292. ;
  2293. ; Output:
  2294. ;   TDP = i000 0000 | 0000 0000 | 0000 0000  (1TC)
  2295. ;
  2296. ;**************************************************************************
  2297.  
  2298.         CLR     A   #<$D2,X0        ;Get '-.71875', set TDP=0
  2299.         CMP     X0,B    #<$80,X1    ;Check A2P, get '1'
  2300.         TLT     X1,A                ;If A2P<-.71875 set TDP=1, else TDP=0
  2301.         MOVE    A1,Y:TDP_R          ;Save TDP
  2302.         MOVE    A1,Y:TD_R           ;Save TDP to TD
  2303.  
  2304. ;**************************************************************************
  2305. ;       TRIGB
  2306. ;
  2307. ; Predictor trigger block
  2308. ;
  2309. ; If TR(k) = 1, An(k)=Bn(k)=TD(k)=0
  2310. ;
  2311. ; Inputs:
  2312. ;   TR = i000 0000 | 0000 0000 | 0000 0000  (1TC)
  2313. ;   BnP = si.ff ffff | ffff ffff | 0000 0000  (16TC)
  2314. ;   AnP = si.ff ffff | ffff ffff | 0000 0000  (16TC)
  2315. ;   TDP = i000 0000 | 0000 0000 | 0000 0000  (1TC)
  2316. ;
  2317. ; Output:
  2318. ;   BnR = si.ff ffff | ffff ffff | 0000 0000  (16TC)
  2319. ;   AnR = si.ff ffff | ffff ffff | 0000 0000  (16TC)
  2320. ;   TDR = i000 0000 | 0000 0000 | 0000 0000  (1TC)
  2321. ;
  2322. ;**************************************************************************
  2323.  
  2324.         MOVE    Y:TR_R,B            ;Get TR
  2325.         TST     B       #0,A        ;Test TR
  2326.         JEQ     <FUNCTF_R           ;If TR=0 continue
  2327.         MOVE    A,Y:TD_R            ;If TR=1, set TDR=0,
  2328.         MOVE    A,Y:(R6)+           ; and B1-B6,A1,A2=0
  2329.         MOVE    A,Y:(R6)+
  2330.         MOVE    A,Y:(R6)+
  2331.         MOVE    A,Y:(R6)+
  2332.         MOVE    A,Y:(R6)+
  2333.         MOVE    A,Y:(R6)+
  2334.         MOVE    A,Y:(R6)+
  2335.         MOVE    A,Y:(R6)+
  2336.  
  2337. ;**************************************************************************
  2338. ;       FUNCTF
  2339. ;
  2340. ; Maps quantizer output I into F(I) function
  2341. ;
  2342. ;  |I(k)|  | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
  2343. ; ---------+---+---+---+---+---+---+---+---+
  2344. ;  F[I(k)] | 7 | 3 | 1 | 1 | 1 | 0 | 0 | 0 |
  2345. ;
  2346. ; Inputs:
  2347. ;   I = siii 0000 | 0000 0000 | 0000 0000
  2348. ;
  2349. ; Output:
  2350. ;   FI = 0iii. 0000 | 0000 0000 | 0000 0000  (3SM)
  2351. ;   IMAG
  2352. ;
  2353. ;**************************************************************************
  2354.  
  2355. FUNCTF_R    MOVE    #<$20,X0
  2356.         MOVE    X:IMAG,A            ;Get |I|
  2357.         CMP     X0,A    #<$50,X0    ;Test for |I|<=2
  2358.         JLE     <RANGE0_R
  2359.         CMP     X0,A    #<$60,X0    ;Test for 3<=|I|<=5
  2360.         JLE     <RANGE1_R
  2361.         CMP     X0,A                ;Test for |I|=6
  2362.         JEQ     <RANGE3_R
  2363.         MOVE    #<$70,A             ;|I|=7, set F[I]=7
  2364.         JMP     <FILTA_R
  2365. RANGE3_R    MOVE    #<$30,A         ;|I|=6, set F[I]=3
  2366.         JMP     <FILTA_R
  2367. RANGE1_R    MOVE    #<$10,A         ;|I|=3,4,or 5, set F[I]=1
  2368.         JMP     <FILTA_R
  2369. RANGE0_R    CLR     A               ;|I|=0,1,or 2, set F[I]=0
  2370.  
  2371. ;**************************************************************************
  2372. ;       FILTA
  2373. ;
  2374. ; Update short term average of F(I)
  2375. ;
  2376. ; DMS(k) = (1 - 2**(-5)) * DMS(k-1) + 2**(-5) * F[I(k)]
  2377. ;
  2378. ; Inputs:
  2379. ;   FI = 0iii. 0000 | 0000 0000 | 0000 0000  (3SM)
  2380. ;   DMS = 0iii. ffff | ffff f000 | 0000 0000  (12SM)
  2381. ;
  2382. ; Output:
  2383. ;   DMSP = 0iii. ffff | ffff f000 | 0000 0000  (12SM)
  2384. ;
  2385. ;**************************************************************************
  2386.  
  2387. FILTA_R MOVE    Y:DMS_R,Y0          ;Get DMS
  2388.         SUB     Y0,A    A,B         ;Find DIF=FI-DMS, save FI
  2389.         MOVE    A,X0    Y:(R7)+,Y1  ;Save DIF, get mask K26
  2390.         MPY     X0,Y1,A Y:(R7)+,X0  ;Find DIFSX=DIF>>5, get mask K27
  2391.         AND     X0,A    Y:DML_R,Y1  ;Truncate DIFSX, get DML
  2392.         ADD     Y0,A    Y:RSHFT+7,X1    ;Find DMSP=DIFSX+DMS
  2393.  
  2394. ;**************************************************************************
  2395. ;       FILTB
  2396. ;
  2397. ; Update long term average of F(I)
  2398. ;
  2399. ; DML(k) = (1 - 2**(-7)) * DML(k-1) + 2**(-7) * F[I(k)]
  2400. ;
  2401. ; Inputs:
  2402. ;   FI = 0iii. 0000 | 0000 0000 | 0000 0000  (3SM)
  2403. ;   DML = 0iii. ffff | ffff fff0 | 0000 0000  (14SM)
  2404. ;
  2405. ; Output:
  2406. ;   DMLP = 0iii. ffff | ffff fff0 | 0000 0000  (14SM)
  2407. ;
  2408. ;**************************************************************************
  2409.  
  2410.         SUB     Y1,B    A1,Y:DMS_R  ;Find DIF=FI-DML
  2411.         MOVE    B1,X0
  2412.         MPY     X0,X1,B Y:(R7)+,X0  ;Find DFISX=DIF>>7, get mask K28
  2413.         AND     X0,B                ;Truncate DIFSX
  2414.         ADD     Y1,B    Y:RSHFT+3,X1    ;Find DMLP=DIFSX+DML
  2415.  
  2416. ;**************************************************************************
  2417. ;       SUBTC
  2418. ;
  2419. ; Compute magnitude of the difference of short and long
  2420. ;  term functions of quantizer output sequence and then
  2421. ;  perform threshold comparison for quantizing speed control
  2422. ;  parameter.
  2423. ;
  2424. ; AX = 1  if Y>=3, TDP=1, & |DMSP-DMLP|>(2**-3)*DMLP
  2425. ;    = 0  otherwise
  2426. ;
  2427. ; Input:
  2428. ;   Y = 0iii i.fff | ffff ff00 | 0000 0000  (13SM)
  2429. ;   DMSP = 0iii. ffff | ffff f000 | 0000 0000  (12SM)
  2430. ;   DMLP = 0iii. ffff | ffff fff0 | 0000 0000  (14SM)
  2431. ;   TDP = i000 0000 | 0000 0000 | 0000 0000  (1TC)
  2432. ;
  2433. ; Output:
  2434. ;   AX = 0i0.0 0000 | 0000 0000 | 0000 0000  (1SM)
  2435. ;
  2436. ;**************************************************************************
  2437.  
  2438.         SUB     B,A     B1,Y:DML_R  ;Find DIF=DMSP-DMLP, save DML
  2439.         ABS     A       B1,Y0       ;Find DIFM=|DIF|
  2440.         MPY     X1,Y0,B     #<$18,Y0    ;Find DTHR=DMLP>>3, get '3'
  2441.         AND     X0,B    #<$40,X0    ;Truncate DTHR, get '1'
  2442.         CMP     B,A     #0,B        ;Compare DIFM & DTHR, set AX=0
  2443.         TGE     X0,B                ;If DIFM>=DTHR set AX=1
  2444.         MOVE    Y:TDP_R,A           ;Get TDP
  2445.         TST     A       X:Y_R,A     ;Check TDP, get Y
  2446.         TNE     X0,B                ;If TDP!=0 set AX=1
  2447.         CMP     Y0,A    X:AP_R,X1   ;Check for Y<"3", get AP
  2448.         TLT     X0,B                ;If Y<"3" set AX=1
  2449.  
  2450. ;**************************************************************************
  2451. ;       FILTC
  2452. ;
  2453. ; Low pass filter of speed control parameter
  2454. ;
  2455. ; AP(k) = (1-2**(-4)) * AP(k-1) + AX
  2456. ;
  2457. ; Inputs:
  2458. ;   AX = 0i0.0 0000 | 0000 0000 | 0000 0000  (1SM)
  2459. ;   AP = 0ii.f ffff | fff0 0000 | 0000 0000  (10SM)
  2460. ;
  2461. ; Outputs:
  2462. ;   APP = 0ii.f ffff | fff0 0000 | 0000 0000  (10SM)
  2463. ;
  2464. ;**************************************************************************
  2465.  
  2466.         SUB     X1,B    Y:RSHFT+4,Y0    ;Find DIF=AX-AP
  2467.         MOVE    B1,X0
  2468.         MPY     X0,Y0,A     Y:(R7)+,X0  ;Find DIFSX=DIF>>4, get K29
  2469.         AND     X0,A    Y:TR_R,B    ;Truncate DIFSX, get TR
  2470.         ADD     X1,A    #<$20,X0    ;Find APP=DIFSX+AP, get '1'
  2471.  
  2472. ;**************************************************************************
  2473. ;       TRIGA
  2474. ;
  2475. ; Speed control trigger block
  2476. ;
  2477. ; AP(k) = AP(k) if TR(k)=0
  2478. ;       =  1    if TR(k)=1
  2479. ;
  2480. ; Inputs:
  2481. ;   TR = i000 0000 | 0000 0000 | 0000 0000  (1TC)
  2482. ;   APP = 0ii.f ffff | fff0 0000 | 0000 0000  (10SM)
  2483. ;
  2484. ; Outputs:
  2485. ;   APR = 0ii.f ffff | fff0 0000 | 0000 0000  (10SM)
  2486. ;
  2487. ;**************************************************************************
  2488.  
  2489.         TST     B   X:IMAG,X1       ;Check TR, get IMAG
  2490.         TMI     X0,A                ;If TR=1 set APR=1, else APR=APP
  2491.         MOVE    A1,X:AP_R           ;Save APR to AP
  2492.  
  2493. ;**************************************************************************
  2494. ;       FUNCTW
  2495. ;
  2496. ; Map quantizer output into logarithmic version of scale
  2497. ;  factor multiplier
  2498. ;
  2499. ;  |I(k)|  |  7  |  6  |  5  |  4  |  3  |  2  |  1  |  0  |
  2500. ; ---------+-----+-----+-----+-----+-----+-----+-----+-----+
  2501. ;   W(I)   |70.13|22.19|12.38| 7.00| 4.00| 2.56| 1.13|-0.75|
  2502. ;
  2503. ; Inputs:
  2504. ;   I = siii. 0000 | 0000 0000 | 0000 0000  (ADPCM format)
  2505. ;
  2506. ; Outputs:
  2507. ;   WI = siii iiii. | ffff 0000 | 0000 0000  (12TC)
  2508. ;
  2509. ;**************************************************************************
  2510.  
  2511.         MOVE    Y:RSHFT+20,X0       ;Get shift constant
  2512.         MPY     X0,X1,A     #WIBASE,R0  ;Shift IM=IMAG for lookup,
  2513.                                     ; load lookup table base
  2514.         MOVE    A1,N0               ;Load IM as offset
  2515.         MOVE    Y:RSHFT+3,X1        ;Get shift constant
  2516.         MOVE    X:Y_R,Y0            ;Get Y
  2517.         MPY     Y0,X1,B     X:(R0+N0),A ;Shift Y>>3,
  2518.                                     ; get WI from lookup table
  2519.  
  2520. ;**************************************************************************
  2521. ;       FILTD
  2522. ;
  2523. ; Update of fast quantizer scale factor
  2524. ;
  2525. ; YU(k) = (1 - 2**(-5)) * Y(k) + 2**(-5) * W[I(k)]
  2526. ;
  2527. ; Inputs:
  2528. ;   WI =  siii iiii. | ffff 0000 | 0000 0000  (12TC)
  2529. ;   Y = 0iii i.fff | ffff ff00 | 0000 0000  (13SM)
  2530. ;
  2531. ; Outputs:
  2532. ;   YUT = 0iii i.fff | ffff ff00 | 0000 0000  (13SM)
  2533. ;
  2534. ;**************************************************************************
  2535.  
  2536.         SUB     B,A                 ;Find DIF=WI-Y
  2537.         ASR     A                   ;Find DIFSX=DIF>>5 (actually DIF>>2)
  2538.         ASR     A   Y:(R7)+,X0      ;Get mask K30
  2539.         AND     X0,A                ;Truncate DIFSX
  2540.         ADD     Y0,A    #<$50,X0    ;Find YUT=DIFSX+Y,
  2541.                                     ; get upper limit '10'
  2542.  
  2543. ;**************************************************************************
  2544. ;       LIMB
  2545. ;
  2546. ; Limit quantizer scale factor
  2547. ;
  2548. ; 1.06 <= YU(k) <= 10.00
  2549. ;
  2550. ; Inputs:
  2551. ;   YUT = 0iii i.fff | ffff ff00 | 0000 0000  (13SM)
  2552. ;
  2553. ; Outputs:
  2554. ;   YUP = 0iii i.fff | ffff ff00 | 0000 0000  (13SM)
  2555. ;
  2556. ;**************************************************************************
  2557.  
  2558.         CMP     X0,A    Y:(R7)+,X1  ;Check for YU>10,
  2559.                                     ; get lower limit '1.06' (K31)
  2560.         TGT     X0,A                ;If YU>10 set YU=10
  2561.         CMP     X1,A    Y:YL_R,Y1   ;Check for YU<1.06, get YL
  2562.         TLT     X1,A                ;If YU<1.06 set YU=1.06
  2563.  
  2564. ;**************************************************************************
  2565. ;       FILTE
  2566. ;
  2567. ; Update of slow quantizer scale factor
  2568. ;
  2569. ; YL(k) = (1 - 2**(-6)) * YL(k-1) + 2**(-6) * YU(k)
  2570. ;
  2571. ; Inputs:
  2572. ;   YUP = 0iii i.fff | ffff ff00 | 0000 0000  (13SM)
  2573. ;   YL = 0iii i.fff | ffff ffff | ffff 0000  (19SM)
  2574. ;
  2575. ; Outputs:
  2576. ;   YLP = 0iii i.fff | ffff ffff | ffff 0000  (19SM)
  2577. ;
  2578. ;**************************************************************************
  2579.  
  2580.         TFR     Y1,B    A1,Y:YU_R   ;Move YL, save YUP
  2581.         NEG     B   Y:(R7)+,Y0      ;Find -YL, save YL, get mask K32
  2582.         AND     Y0,B    #CONST4,R7  ;Truncate -YL (-YL>>6),
  2583.                                     ; adjust constant pointer
  2584.         ADD     B,A     Y:RSHFT+6,Y0    ;Find DIF=YUP+(-YL>>6)
  2585.         MOVE    A1,X1
  2586.         MPY     Y0,X1,A     #$002100,Y0     ;Find DIFSX>>6, get bias
  2587.         ADD     Y1,A    Y:LAW,B     ;Find YLP=DIFSX+YL
  2588.         MOVE    A1,Y:YL_R           ;Save YL
  2589.  
  2590. ;**************************************************************************
  2591. ;       COMPRESS
  2592. ;
  2593. ; Convert from uniform PCM to A-law or mu-law PCM (according to
  2594. ;   Recommendation G.711). For further details see Motorola
  2595. ;   application bulletin "Logarithmic/Linear Conversion
  2596. ;   Routines for DSP56000/1".
  2597. ;
  2598. ; Input:
  2599. ;   SR = siii iiii | iiii iiii. | 0000 0000  (16TC)
  2600. ;
  2601. ; Output:
  2602. ;   SP = psss qqqq | 0000 0000 | 0000 0000 (PCM log format)
  2603. ;
  2604. ;**************************************************************************
  2605.  
  2606.         TST     B       Y:SR_R,A    ;Adjust constant pointer
  2607.         JNE     <ALAW_R
  2608.  
  2609. ; Linear to log routine for mu-law
  2610.         ABS     A       A,B         ;Find |SR|, save sign
  2611.         ADD     Y0,A                ;Add bias
  2612.         ASL     A   #TAB+7,R0       ;Shift << 2, get seg ptr
  2613.         ASL     A   X:TAB+3,X0      ; and get max. word
  2614.         TES     X0,A                ;If overflow in extension
  2615.                                     ; set the maximum PCM word
  2616.         NORM    R0,A                ;Find MSB of data
  2617.         NORM    R0,A
  2618.         NORM    R0,A
  2619.         NORM    R0,A
  2620.         NORM    R0,A
  2621.         NORM    R0,A
  2622.         NORM    R0,A
  2623.         ASL     A       #<$20,Y0
  2624.         LSL     B       A1,X0
  2625.         MPY     X0,Y0,A     X:(R0),X1
  2626.         AND     X1,A
  2627.         ROR     A
  2628.         NOT     A       #<$FF,X0
  2629.         AND     X0,A
  2630.         MOVE    A1,A
  2631.         JMP     <SAVESP_R
  2632.  
  2633. ; Linear to log routine for A-law
  2634. ALAW_R  ABS     A       A,B         ;Find |SR|, save sign
  2635.         TST     B       #$000100,X0
  2636.         JPL     <NOSUB_R
  2637.         SUB     X0,A
  2638. NOSUB_R MOVE    #$7FFE00,X0
  2639.         AND     X0,A
  2640.         ASL     A   #TAB+7,R0       ;Shift << 2, get seg ptr
  2641.         ASL     A   X:TAB+3,X0      ; and get max. word
  2642.         TES     X0,A                ;If overflow in extension
  2643.                                     ; set the maximum PCM word
  2644.         NORM    R0,A                ;Find MSB of data
  2645.         NORM    R0,A
  2646.         NORM    R0,A
  2647.         NORM    R0,A
  2648.         NORM    R0,A
  2649.         NORM    R0,A
  2650.         JNR     <SEGOK_R
  2651.         MOVE    (R0)-
  2652. SEGOK_R LSL     A       #<$20,Y0
  2653.         LSL     B       A1,X0
  2654.         MPY     X0,Y0,A     X:(R0),X1
  2655.         AND     X1,A
  2656.         ROR     A       #<$D5,Y1
  2657.         EOR     Y1,A    #<$FF,X0    ;Invert even bits & sign
  2658.         AND     X0,A
  2659.         MOVE    A1,A
  2660. SAVESP_R    MOVE    A1,X:SP_R
  2661.  
  2662. ;**************************************************************************
  2663. ;       EXPAND
  2664. ;
  2665. ; Convert A-law or mu-law PCM to uniform PCM (according to
  2666. ;   Recommendation G.711). For further details see Motorola
  2667. ;   application bulletin "Logarithmic/Linear Conversion
  2668. ;   Routines for DSP56000/1".
  2669. ;
  2670. ; Input:
  2671. ;   SP = psss qqqq | 0000 0000 | 0000 0000 (PCM log format)
  2672. ;
  2673. ; Output:
  2674. ;   SLX = siii iiii | iiii ii.00 | 0000 0000  (14TC)
  2675. ;
  2676. ;**************************************************************************
  2677.  
  2678.         MOVE    A,X0        Y:(R7)+,Y1  ;Get shift constant K4
  2679.         MPY     X0,Y1,A     Y:(R7)+,X1  ;Shift S to 8 lsb's of A1, get K5
  2680.         AND     X1,A    Y:SE_R,B    ;Mask off sign of S, get SE
  2681.         ASR     B       A1,N3       ;Sign extend SE, load |S| as offset
  2682.         CMPM    Y1,A                ;Check sign of S
  2683.         MOVE    X:(R3+N3),A         ;Lookup |SLX| from ROM table
  2684.         JGE     <SUBTA_R            ;If S=0, SLX=|SLX|
  2685.         NEG     A                   ;If S=1, SLX=-|SLX|
  2686.  
  2687. ;**************************************************************************
  2688. ;       SUBTA
  2689. ;
  2690. ; Compute difference signal by subtracting signal estimate
  2691. ;       from input signal
  2692. ;
  2693. ;   DX(k) = SLX(k) - SE(k)
  2694. ;
  2695. ; Inputs:
  2696. ;   SLX = siii iiii | iiii ii.00 | 0000 0000  (14TC) 
  2697. ;   SE = siii iiii | iiii iii.0 | 0000 0000  (15TC)
  2698. ;
  2699. ; Output:
  2700. ;   DX = siii iiii | iiii iiii. | 0000 0000  (16TC)
  2701. ;**************************************************************************
  2702.  
  2703. SUBTA_R ASR     A       Y:(R7)+,X1  ;Sign extend SLX, get mask K6
  2704.         ASR     A       #$000E,R0   ;Sign extend SE again, get exp bias (14)
  2705.         SUB     B,A     X:Y_R,B     ;Find DX=SLX-SE, get Y
  2706.  
  2707. ;**************************************************************************
  2708. ;       LOG
  2709. ;
  2710. ; Convert difference signal from the linear to the log
  2711. ;   domain
  2712. ;
  2713. ; Input:
  2714. ;   DX = siii iiii | iiii iiii. | 0000 0000  (16TC)
  2715. ;
  2716. ; Outputs:
  2717. ;   DLX = 0iii i.fff | ffff 0000 | 0000 0000  (11SM)
  2718. ;   DSX = sXXX XXXX | XXXX XXXX | 0000 0000  (1TC)
  2719. ;
  2720. ;**************************************************************************
  2721.  
  2722.         ABS     A   A,Y1            ;Find DQM=|D|, save DSX to Y1
  2723.         JNE     <NORMEXP_R          ;Check for DQM=0
  2724.         CLR     A       (R7)+       ;If DQM=0 set DL=0,
  2725.         MOVE    Y:(R7),X0           ; get mask K8,
  2726.         JMP     <SUBTB_R            ; and continue
  2727. NORMEXP_R   NORM    R0,A            ;If DQM!=0, do norm iteration
  2728.         NORM    R0,A                ; 14 times to find MSB of DQM
  2729.         NORM    R0,A
  2730.         NORM    R0,A
  2731.         NORM    R0,A
  2732.         NORM    R0,A
  2733.         NORM    R0,A
  2734.         NORM    R0,A
  2735.         NORM    R0,A
  2736.         NORM    R0,A
  2737.         NORM    R0,A
  2738.         NORM    R0,A
  2739.         NORM    R0,A
  2740.         NORM    R0,A
  2741. ;   A1 = 01?? ???? | ???? ???? | 0000 0000 = normalized DQM  (A2=A0=0)
  2742. ;   R0 = 0000 0000 | 0000 eeee = exponent of normalized DQM
  2743.  
  2744. ;   Get rid of leading "1" in normalized DQM
  2745. ;   Truncate mantissa to 7 bits and combine with exponent
  2746.         AND     X1,A    Y:LSHFT-19,X0   ;Truncate MANT, get EXP shift
  2747. ;   A1 = 00mm mmmm | m000 0000 | 0000 0000 (A2=A0=0)
  2748.         MOVE    R0,X1               ;Move EXP to X1
  2749.         MPY     X0,X1,A     A,X1    Y:(R7)+,Y0 ;Shift EXP<<19, save MANT to X1,
  2750.                                     ; get mask K7
  2751.         MOVE    A0,A                ;Move EXP to A1
  2752. ;   A1 = 0eee e000 | 0000 0000 | 0000 0000 (A2=A0=0)
  2753.         MAC     Y0,X1,A     Y:(R7),X0   ;Shift MANT>>3 & combine with EXP,
  2754.                                         ; get mask K8
  2755. ;   A1 = 0eee e.mmm | mmmm 0000 | 0000 0000  (A2=A0=0)
  2756. ;      = 0iii i.fff | ffff 0000 | 0000 0000  (A2=A0=0)
  2757.  
  2758. ;**************************************************************************
  2759. ;       SUBTB
  2760. ;
  2761. ; Scale log version of difference signal by subtracting
  2762. ;   scale factor
  2763. ;
  2764. ; DLNX = DLX - Y
  2765. ;
  2766. ; Inputs:
  2767. ;   DLX = 0iii i.fff | ffff 0000 | 0000 0000  (11SM)
  2768. ;   Y = 0iii i.fff | ffff ff00 | 0000 0000  (13SM)
  2769. ;
  2770. ; Output:
  2771. ;   DLNX = siii i.fff | ffff 0000 | 0000 0000 (12TC)
  2772. ;
  2773. ;**************************************************************************
  2774.  
  2775. SUBTB_R AND     X0,B    #QUANTAB,R0     ;Truncate Y to 11 bits (Y>>2),
  2776.                                         ; get quantization table base
  2777.         SUB     B,A     #>QUANTAB+2,X1  ;Find DLNX=DLX-Y
  2778.  
  2779. ;**************************************************************************
  2780. ;       SYNC
  2781. ;
  2782. ; Re-encode output PCM sample in decoder for synchronous
  2783. ;   tandem coding
  2784. ;
  2785. ; Inputs:
  2786. ;   I = siii 0000 | 0000 0000 | 0000 0000 (ADPCM format)
  2787. ;   SP = psss qqqq | 0000 0000 | 0000 0000 (PCM log format)
  2788. ;   DLNX = siii i.fff | ffff 0000 | 0000 0000 (12TC)
  2789. ;   DSX = sXXX XXXX | XXXX XXXX | 0000 0000  (1TC)
  2790. ;
  2791. ; Output:
  2792. ;   SD = psss qqqq | 0000 0000 | 0000 0000 (PCM log format)
  2793. ;
  2794. ;**************************************************************************
  2795.  
  2796.         MOVE    X:(R0)+,X0          ;Get quan table value
  2797. TSTDLN_R    CMP     X0,A    X:(R0)+,X0  ;Compare to DLNX
  2798.         JGE     <TSTDLN_R           ;If value<DLNX try next range
  2799.         MOVE    R0,A                ;When range found...
  2800.                                     ; subtract pointer from
  2801.         SUB     X1,A    Y:LSHFT-19,X0   ; base to get |ID|  
  2802. ;   A1 = 0000 0000 | 0000 0000 | 0000 0iii (A2=A0=0)
  2803.         MOVE    A1,X1
  2804.         MPY     X0,X1,A     Y1,B    ;Shift |ID|<<19, result is
  2805.                                     ; in A0, move DSX into B
  2806. ;   A0 = 00ii i000 | 0000 0000 | 0000 0000
  2807.         MOVE    A0,A
  2808. ;   A1 = 00ii i000 | 0000 0000 | 0000 0000 (A2=A0=0)
  2809.         TST     A       #<$78,X0    ;Check |ID|, get invert mask
  2810.         JEQ     <INVERT_R           ;If |ID|=0 invert bits
  2811.         TST     B                   ;If |ID|!=0, check DSX
  2812.         JPL     <IOUT_R             ;If DSX=1 don't invert |ID|
  2813. INVERT_R    EOR     X0,A            ;If DSX=0 or |ID|=0,
  2814.                                     ; invert |ID|
  2815. IOUT_R  MOVE    #<$40,X0
  2816.         EOR     X0,A    X:I_R,B     ;Invert MSB of ID, get I
  2817.         TST     B       A1,A        ;Adjust sign extension, check IS
  2818.  
  2819.         JMI     <ANDW7_R            ;If IS=1, AND with 7
  2820.         MOVE    #<$80,X0            ;If IS=0,
  2821.         EOR     X0,B                ; find IM=I+8
  2822.         JMP     <FIXS_R
  2823. ANDW7_R MOVE    #<$70,X0
  2824.         AND     X0,B                ;Find IM=I&7
  2825.  
  2826. FIXS_R  LSR     B
  2827.         MOVE    B1,B
  2828. ;   A1 = 0iii i000 | 0000 0000 | 0000 0000 (A2=A0=0)
  2829. ;   B1 = 0iii i000 | 0000 0000 | 0000 0000 (B2=B0=0)
  2830.         SUB     B,A     Y:LAW,B
  2831.         TST     B
  2832.         JNE     <ALAWDEC_R
  2833.  
  2834.         TST     A       X:SP_R,A    ;Compare ID and IM, get SP
  2835.         JEQ     <SAVESD_R           ;If ID=IM, SD=SP
  2836.         JLT     <SPPLUS_R           ;If ID<IM, SD=SP+
  2837.                                     ;Else ID>IM, SD=SP-
  2838.         TST     A       #<$80,X0
  2839.         JEQ     <SAVESD_R           ;If SP=0, SP-=SP
  2840.         CMP     X0,A    #<$FF,X0
  2841.         JEQ     <INCSP_R            ;If SP=$80, SP-=SP+1
  2842.         CMP     X0,A    #<$7F,X0
  2843.         JEQ     <SETNEG1_R          ;If SP=$FF, SP-=$7E
  2844.         CMP     X0,A
  2845.         JEQ     <DECSP_R            ;If SP=$7F, SP-=SP-1
  2846.         TST     A
  2847.         JPL     <DECSP_R            ;Else if SPS=1, SP-=SP-1
  2848.         JMP     <INCSP_R            ;Else SPS=0, SP-=SP+1
  2849.  
  2850. SPPLUS_R    TST     A       #<$80,X0
  2851.         JEQ     <INCSP_R            ;If SP=0, SP+=SP+1
  2852.         CMP     X0,A    #<$FF,X0
  2853.         JEQ     <SAVESD_R               ;If SP=$80, SP+=SP
  2854.         CMP     X0,A    #<$7F,X0
  2855.         JEQ     <DECSP_R            ;If SP=$FF, SP+=SP-1
  2856.         CMP     X0,A
  2857.         JEQ     <SET1_R             ;If SP=$7F, SP+=$FE
  2858.         TST     A
  2859.         JPL     <INCSP_R            ;Else if SPS=1, SP+=SP+1
  2860.         JMP     <DECSP_R            ;Else SPS=0, SP+=SP-1
  2861.  
  2862. INCSP_R MOVE    #<$01,X0
  2863.         ADD     X0,A                ;Find SD=SP+1
  2864.         JMP     <SAVESD_R
  2865. DECSP_R MOVE    #<$01,X0
  2866.         SUB     X0,A                ;Find SD=SP-1
  2867.         JMP     <SAVESD_R
  2868. SET1_R  MOVE    #<$FE,A             ;Find SD=$FE
  2869.         JMP     <SAVESD_R
  2870. SETNEG1_R   MOVE    #<$7E,A             ;Find SD=$7E
  2871.         JMP     <SAVESD_R
  2872.  
  2873.  
  2874. ALAWDEC_R   MOVE    A,B
  2875.         MOVE    X:SP_R,A                    ;Get SP
  2876.         MOVE    #<$55,X0
  2877.         EOR     X0,A
  2878.         TST     B
  2879.         JEQ     <INVEVEN_R          ;If ID=IM, SD=SP
  2880.         JLT     <SPPLUSA_R          ;If ID<IM, SD=SP+
  2881.                                     ;Else ID>IM, SD=SP-
  2882.         TST     A       #<$80,X0
  2883.         JEQ     <INCSPA_R           ;If SP=0, SP-=SP+1
  2884.         CMP     X0,A    #<$FF,X0
  2885.         JEQ     <SETNEG0_R          ;If SP=$80, SP-=0
  2886.         CMP     X0,A    #<$7F,X0
  2887.         JEQ     <DECSPA_R               ;If SP=$FF, SP-=SP-1
  2888.         CMP     X0,A
  2889.         JEQ     <INVEVEN_R          ;If SP=$7F, SP-=SP
  2890.         TST     A
  2891.         JMI     <DECSPA_R           ;Else if SPS=0, SP-=SP-1
  2892.         JMP     <INCSPA_R           ;Else SPS=1, SP-=SP+1
  2893.  
  2894. SPPLUSA_R   TST     A       #<$80,X0
  2895.         JEQ     <SET0_R             ;If SP=0, SP+=$80
  2896.         CMP     X0,A    #<$FF,X0
  2897.         JEQ     <INCSPA_R           ;If SP=$80, SP+=SP+1
  2898.         CMP     X0,A    #<$7F,X0
  2899.         JEQ     <INVEVEN_R          ;If SP=$FF, SP+=SP
  2900.         CMP     X0,A
  2901.         JEQ     <DECSPA_R           ;If SP=$7F, SP+=SP-1
  2902.         TST     A
  2903.         JMI     <INCSPA_R           ;Else if SPS=0, SP+=SP+1
  2904.         JMP     <DECSPA_R           ;Else SPS=1, SP+=SP-1
  2905.  
  2906. INCSPA_R    MOVE    #<$01,X0
  2907.         ADD     X0,A                ;Find SD=SP+1
  2908.         JMP     <INVEVEN_R
  2909. DECSPA_R    MOVE    #<$01,X0
  2910.         SUB     X0,A                ;Find SD=SP-1
  2911.         JMP     <INVEVEN_R
  2912. SET0_R  MOVE    #<$80,A             ;Find SD=$80
  2913.         JMP     <INVEVEN_R
  2914. SETNEG0_R   CLR     A                   ;Find SD=0
  2915. INVEVEN_R   MOVE    #<$55,X0
  2916.         EOR     X0,A
  2917.     
  2918. SAVESD_R    MOVE    #2,X0
  2919.         JSR     $E004
  2920.  
  2921.         MOVE    R2,X:DATAPTR_R
  2922.  
  2923.         JMP     <ENCODE
  2924.  
  2925. ;**************************************************************************
  2926. ;       INIT
  2927. ;
  2928. ; Initialize program variables, transfer data tables to X and Y
  2929. ; memory, and set up registers
  2930. ;
  2931. ;**************************************************************************
  2932.  
  2933. INIT    MOVE    #0,R0
  2934.         MOVE    #0,R4
  2935.         REP     #$7F
  2936.         MOVE    A,X:(R0)+   A,Y:(R4)+   ;Clear X & Y internal RAM
  2937.  
  2938. ; X memory initialization
  2939.  
  2940.         MOVE    #$3E2000,X0
  2941.         MOVE    X0,X:AP_T           ;Initialize AP_T & AP_R
  2942.         MOVE    A0,X:AP_R
  2943.         MOVE    #DATA_T,A0          ;Set transmit data pointer
  2944.         MOVE    A0,X:DATAPTR_T      ; to start of transmit data buffer
  2945.         MOVE    #DATA_R,A0          ;Set receive data pointer
  2946.         MOVE    A0,X:DATAPTR_R      ; to start of receive data buffer
  2947.         MOVE    #VARINIT,R0
  2948.         MOVE    #QUANTAB,R3
  2949.         DO      #38,XTABLES
  2950.         MOVE    P:(R0)+,X0          ;Transfer constant tables
  2951.         MOVE    X0,X:(R3)+          ; into X memory
  2952. XTABLES
  2953.         MOVE    #DATA_T+1,R3
  2954.         MOVE    #<$4,X0
  2955.         MOVE    #<$8,X1
  2956.         DO      #6,XBUFFER1
  2957.         MOVE    X0,X:(R3)+          ;Initialize SRnMANT and SRnS vars
  2958.         MOVE    X1,X:(R3)+          ; in the transmit data buffer
  2959.         MOVE    (R3)+
  2960. XBUFFER1
  2961.         MOVE    X0,X:(R3)+          ;Initialize SR1MANT (transmit)
  2962.         MOVE    (R3)+
  2963.         MOVE    (R3)+
  2964.         MOVE    X0,X:(R3)+          ;Initialize SR2MANT (transmit)
  2965.         MOVE    #DATA_R+1,R3
  2966.         DO      #6,XBUFFER2
  2967.         MOVE    X0,X:(R3)+          ;Initialize SRnMANT and SRnS vars
  2968.         MOVE    X1,X:(R3)+          ; in the receive data buffer
  2969.         MOVE    (R3)+
  2970. XBUFFER2
  2971.         MOVE    X0,X:(R3)+          ;Initialize SR1MANT (receive)
  2972.         MOVE    (R3)+
  2973.         MOVE    (R3)+
  2974.         MOVE    X0,X:(R3)+          ;Initialize SR2MANT (receive)
  2975.  
  2976. ; Y memory initialization
  2977.  
  2978.         MOVE    #$088000,X0
  2979.         MOVE    X0,Y:YU_T           ;Initialize YU_T,
  2980.         MOVE    X0,Y:YL_T           ; & YL_T
  2981.         MOVE    X0,Y:YU_R           ;Initialize YU_R,
  2982.         MOVE    X0,Y:YL_R           ; & YL_R
  2983.         MOVE    #RSHFT,R3
  2984.         DO      #56,YTABLES
  2985.         MOVE    P:(R0)+,X0          ;Transfer constant tables
  2986.         MOVE    X0,Y:(R3)+          ; into Y memory
  2987. YTABLES
  2988.  
  2989. ; Address register initialization
  2990.  
  2991.         MOVEC   #7,M1               ;Set partial product buffer for mod(7)
  2992.         MOVEC   #23,M2              ;Set data buffer for mod(23)
  2993.         MOVEC   #7,M6               ;Set coef buffer for mod(7)
  2994.         MOVEC   #$7F,M3             ;Set PCM table for mod(127)
  2995.         MOVE    #0,A                ;Select mu-law or A-law,
  2996.         MOVE    A,Y:LAW             ; for mu-law set LAW=0 (default),
  2997.                                     ; for A-law set LAW!=0
  2998.         TST     A       #$100,R3    ;If LAW=0 select mu-law table
  2999.         JEQ     <SETR5              ; base (in X ROM), otherwise
  3000.         MOVE    #$180,R3            ; select A-law table base
  3001. SETR5   MOVE    #RSHFT,R5           ;Set right shift table base
  3002.         RTS
  3003.  
  3004. ;QUANTAB
  3005. VARINIT     DC      $F84000         ;-0.98
  3006.             DC      $050000         ;0.62
  3007.             DC      $0B2000         ;1.38
  3008.             DC      $0F6000         ;1.91
  3009.             DC      $12C000         ;2.34
  3010.             DC      $15D000         ;2.72
  3011.             DC      $190000         ;3.12
  3012.             DC      $7FFFFF         ;15.99
  3013. ;IQUANTAB
  3014.             DC      $800000         ;-16    |I|=0
  3015.             DC      $004000         ;0.031  |I|=1
  3016.             DC      $087000         ;1.05   |I|=2
  3017.             DC      $0D5000         ;1.66   |I|=3
  3018.             DC      $111000         ;2.13   |I|=4
  3019.             DC      $143000         ;2.52   |I|=5
  3020.             DC      $175000         ;2.91   |I|=6
  3021.             DC      $1A9000         ;3.32   |I|=7
  3022. ;WIBASE
  3023.             DC      $FF4000         ;-0.75  |I|=0
  3024.             DC      $012000         ;1.13   |I|=1
  3025.             DC      $029000         ;2.56   |I|=2
  3026.             DC      $040000         ;4.00   |I|=3
  3027.             DC      $070000         ;7.00   |I|=4
  3028.             DC      $0C6000         ;12.38  |I|=5
  3029.             DC      $163000         ;22.19  |I|=6
  3030.             DC      $462000         ;70.13  |I|=7
  3031. ;TAB
  3032.             DC      $1E0000
  3033.             DC      $3E0000
  3034.             DC      $5E0000
  3035.             DC      $7E0000
  3036.             DC      $9E0000
  3037.             DC      $BE0000
  3038.             DC      $DE0000
  3039.             DC      $FE0000
  3040. ;CONST - constants used in FMULT
  3041.             DC      $FFFC00         ;KF1 = trunc mask
  3042.             DC      $7FFC00         ;KF2 = trunc mask
  3043.             DC      $018000         ;KF3 = '48'
  3044.             DC      $7F8000         ;KF4 = trunc mask
  3045.             DC      $00001A         ;KF5 = '26'
  3046.             DC      $7FFF00         ;KF6 = trunc mask
  3047.  
  3048. ;RSHFT
  3049.             DC      $800000
  3050.             DC      $400000         ;>>1    <<23
  3051.             DC      $200000         ;>>2    <<22
  3052.             DC      $100000         ;>>3    <<21
  3053.             DC      $080000         ;>>4    <<20
  3054.             DC      $040000         ;>>5    <<19
  3055.             DC      $020000         ;>>6    <<18
  3056.             DC      $010000         ;>>7    <<17
  3057.             DC      $008000         ;>>8    <<16
  3058.             DC      $004000         ;>>9    <<15
  3059.             DC      $002000         ;>>10   <<14
  3060.             DC      $001000         ;>>11   <<13
  3061.             DC      $000800         ;>>12   <<12
  3062.             DC      $000400         ;>>13   <<11
  3063.             DC      $000200         ;>>14   <<10
  3064.             DC      $000100         ;>>15   <<9
  3065.             DC      $000080         ;>>16   <<8
  3066.             DC      $000040         ;>>17   <<7
  3067.             DC      $000020         ;>>18   <<6
  3068.             DC      $000010         ;>>19   <<5
  3069.             DC      $000008         ;>>20   <<4
  3070.             DC      $000004         ;>>21   <<3
  3071.             DC      $000002         ;>>22   <<2
  3072.             DC      $000001         ;>>23   <<1
  3073. ;CONST1
  3074.             DC      $FFFE00         ;K1 = trunc mask (ACCUM)
  3075.             DC      $7FFC00         ;K2 = trunc mask (MIX)
  3076.             DC      $7FFE00         ;K3 = trunc mask (MIX)
  3077.             DC      $000080         ;K4 = shift const (EXPAND)
  3078.             DC      $00007F         ;K5 = sign mask (EXPAND)
  3079.             DC      $3F8000         ;K6 = trunc mask (LOG)
  3080.             DC      $100000         ;K7 = shift const (LOG)
  3081.             DC      $7FF000         ;K8 = trunc mask (SUBTB & ADDA)
  3082.             DC      $07F000         ;K9 = sign mask (ANTILOG)
  3083.             DC      $00000A         ;K10 = '10' (ANTILOG)
  3084.             DC      $7FFE00         ;K11 = trunc mask (ANTILOG)
  3085.             DC      $07C000         ;K12 = trunc mask (TRANS)
  3086.             DC      $000010         ;K13 = shift const (TRANS)
  3087.             DC      $000008         ;K14 = '8' (TRANS)
  3088.             DC      $000005         ;K15 = '5' (TRANS)
  3089.             DC      $7FFE00         ;K16 = trunc mask (TRANS)
  3090.             DC      $008000         ;K17 = +gain (UPB)
  3091.             DC      $FF8000         ;K18 = -gain (UPB)
  3092.             DC      $FFFF00         ;K19 = trunc mask (UPB)
  3093.             DC      $1FFF00         ;K20 = '+1.99' (UPA2)
  3094.             DC      $E00100         ;K21 = '-1.99' (UPA2)
  3095.             DC      $FFFF00         ;K22 = trunc mask (UPA2)
  3096.             DC      $FF4000         ;K23 = -gain (UPA1)
  3097.             DC      $00C000         ;K24 = +gain (UPA1)
  3098.             DC      $FFFF00         ;K25 = trunc mask (UPA1)
  3099.             DC      $040000         ;K26 = shift const (FILTA)
  3100.             DC      $FFF800         ;K27 = trunc mask (FILTA)
  3101.             DC      $FFFE00         ;K28 = trunc mask (FILTB)
  3102.             DC      $FFE000         ;K29 = trunc mask (FILTC)
  3103.             DC      $FFFC00         ;K30 = trunc mask (FILTD)
  3104.             DC      $088000         ;K31 = '1.06' (LIMB)
  3105.             DC      $FFFC00         ;K32 = trunc mask (FILTE)
  3106.